linux-old/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 <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/seq_file.h>
  24#include <linux/kdev_t.h>
  25#include <linux/major.h>
  26#include <linux/string.h>
  27#include <linux/blk.h>
  28#include <linux/init.h>
  29#include <linux/interrupt.h>
  30#include <linux/console.h>
  31#include <linux/spinlock.h>
  32
  33#include <asm/segment.h>
  34#include <asm/system.h>
  35#include <asm/io.h>
  36#include <asm/kgdb.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/kdebug.h>
  44#include <asm/mbus.h>
  45#include <asm/idprom.h>
  46#include <asm/softirq.h>
  47#include <asm/hardirq.h>
  48#include <asm/machines.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;
  69extern int serial_console;
  70extern void breakpoint(void);
  71#if CONFIG_SUN_CONSOLE
  72void (*prom_palette)(int);
  73#endif
  74asmlinkage void sys_sync(void); /* it's really int */
  75
  76/* Pretty sick eh? */
  77void prom_sync_me(void)
  78{
  79        unsigned long prom_tbr, flags;
  80
  81        /* XXX Badly broken. FIX! - Anton */
  82        save_and_cli(flags);
  83        __asm__ __volatile__("rd %%tbr, %0\n\t" : "=r" (prom_tbr));
  84        __asm__ __volatile__("wr %0, 0x0, %%tbr\n\t"
  85                             "nop\n\t"
  86                             "nop\n\t"
  87                             "nop\n\t" : : "r" (&trapbase));
  88
  89#ifdef CONFIG_SUN_CONSOLE
  90        if (prom_palette)
  91                prom_palette(1);
  92#endif
  93        prom_printf("PROM SYNC COMMAND...\n");
  94        show_free_areas();
  95        if(current->pid != 0) {
  96                sti();
  97                sys_sync();
  98                cli();
  99        }
 100        prom_printf("Returning to prom\n");
 101
 102        __asm__ __volatile__("wr %0, 0x0, %%tbr\n\t"
 103                             "nop\n\t"
 104                             "nop\n\t"
 105                             "nop\n\t" : : "r" (prom_tbr));
 106        restore_flags(flags);
 107
 108        return;
 109}
 110
 111extern void rs_kgdb_hook(int tty_num); /* sparc/serial.c */
 112
 113unsigned int boot_flags __initdata = 0;
 114#define BOOTME_DEBUG  0x1
 115#define BOOTME_SINGLE 0x2
 116#define BOOTME_KGDBA  0x4
 117#define BOOTME_KGDBB  0x8
 118#define BOOTME_KGDB   0xc
 119
 120#ifdef CONFIG_SUN_CONSOLE
 121static int console_fb __initdata = 0;
 122#endif
 123
 124/* Exported for mm/init.c:paging_init. */
 125unsigned long cmdline_memory_size __initdata = 0;
 126
 127void kernel_enter_debugger(void)
 128{
 129        if (boot_flags & BOOTME_KGDB) {
 130                printk("KGDB: Entered\n");
 131                breakpoint();
 132        }
 133}
 134
 135static void
 136prom_console_write(struct console *con, const char *s, unsigned n)
 137{
 138        prom_printf("%s", s);
 139}
 140
 141static struct console prom_debug_console = {
 142        name:           "debug",
 143        write:          prom_console_write,
 144        flags:          CON_PRINTBUFFER,
 145        index:          -1,
 146};
 147
 148int obp_system_intr(void)
 149{
 150        if (boot_flags & BOOTME_KGDB) {
 151                printk("KGDB: system interrupted\n");
 152                breakpoint();
 153                return 1;
 154        }
 155        if (boot_flags & BOOTME_DEBUG) {
 156                printk("OBP: system interrupted\n");
 157                prom_halt();
 158                return 1;
 159        }
 160        return 0;
 161}
 162
 163/* 
 164 * Process kernel command line switches that are specific to the
 165 * SPARC or that require special low-level processing.
 166 */
 167static void __init process_switch(char c)
 168{
 169        switch (c) {
 170        case 'd':
 171                boot_flags |= BOOTME_DEBUG;
 172                break;
 173        case 's':
 174                boot_flags |= BOOTME_SINGLE;
 175                break;
 176        case 'h':
 177                prom_printf("boot_flags_init: Halt!\n");
 178                prom_halt();
 179                break;
 180        case 'p':
 181                /* Use PROM debug console. */
 182                register_console(&prom_debug_console);
 183                break;
 184        default:
 185                printk("Unknown boot switch (-%c)\n", c);
 186                break;
 187        }
 188}
 189
 190static void __init boot_flags_init(char *commands)
 191{
 192        while (*commands) {
 193                /* Move to the start of the next "argument". */
 194                while (*commands && *commands == ' ')
 195                        commands++;
 196
 197                /* Process any command switches, otherwise skip it. */
 198                if (*commands == '\0')
 199                        break;
 200                else if (*commands == '-') {
 201                        commands++;
 202                        while (*commands && *commands != ' ')
 203                                process_switch(*commands++);
 204                } else if (strlen(commands) >= 9
 205                           && !strncmp(commands, "kgdb=tty", 8)) {
 206                        switch (commands[8]) {
 207#ifdef CONFIG_SUN_SERIAL
 208                        case 'a':
 209                                boot_flags |= BOOTME_KGDBA;
 210                                prom_printf("KGDB: Using serial line /dev/ttya.\n");
 211                                break;
 212                        case 'b':
 213                                boot_flags |= BOOTME_KGDBB;
 214                                prom_printf("KGDB: Using serial line /dev/ttyb.\n");
 215                                break;
 216#endif
 217                        default:
 218                                printk("KGDB: Unknown tty line.\n");
 219                                break;
 220                        }
 221                        commands += 9;
 222                } else {
 223#if CONFIG_SUN_CONSOLE
 224                        if (!strncmp(commands, "console=", 8)) {
 225                                commands += 8;
 226                                if (!strncmp (commands, "ttya", 4)) {
 227                                        console_fb = 2;
 228                                        prom_printf ("Using /dev/ttya as console.\n");
 229                                } else if (!strncmp (commands, "ttyb", 4)) {
 230                                        console_fb = 3;
 231                                        prom_printf ("Using /dev/ttyb as console.\n");
 232#if defined(CONFIG_PROM_CONSOLE)
 233                                } else if (!strncmp (commands, "prom", 4)) {
 234                                        char *p;
 235                                        
 236                                        for (p = commands - 8; *p && *p != ' '; p++)
 237                                                *p = ' ';
 238                                        conswitchp = &prom_con;
 239                                        console_fb = 1;
 240#endif
 241                                } else {
 242                                        console_fb = 1;
 243                                }
 244                        } else
 245#endif
 246                        if (!strncmp(commands, "mem=", 4)) {
 247                                /*
 248                                 * "mem=XXX[kKmM] overrides the PROM-reported
 249                                 * memory size.
 250                                 */
 251                                cmdline_memory_size = simple_strtoul(commands + 4,
 252                                                             &commands, 0);
 253                                if (*commands == 'K' || *commands == 'k') {
 254                                        cmdline_memory_size <<= 10;
 255                                        commands++;
 256                                } else if (*commands=='M' || *commands=='m') {
 257                                        cmdline_memory_size <<= 20;
 258                                        commands++;
 259                                }
 260                        }
 261                        while (*commands && *commands != ' ')
 262                                commands++;
 263                }
 264        }
 265}
 266
 267/* This routine will in the future do all the nasty prom stuff
 268 * to probe for the mmu type and its parameters, etc. This will
 269 * also be where SMP things happen plus the Sparc specific memory
 270 * physical memory probe as on the alpha.
 271 */
 272
 273extern int prom_probe_memory(void);
 274extern void sun4c_probe_vac(void);
 275extern char cputypval;
 276extern unsigned long start, end;
 277extern void panic_setup(char *, int *);
 278extern void srmmu_end_memory(unsigned long, unsigned long *);
 279extern void sun_serial_setup(void);
 280
 281extern unsigned short root_flags;
 282extern unsigned short root_dev;
 283extern unsigned short ram_flags;
 284#define RAMDISK_IMAGE_START_MASK        0x07FF
 285#define RAMDISK_PROMPT_FLAG             0x8000
 286#define RAMDISK_LOAD_FLAG               0x4000
 287
 288extern int root_mountflags;
 289
 290char saved_command_line[256];
 291char reboot_command[256];
 292enum sparc_cpu sparc_cpu_model;
 293
 294struct tt_entry *sparc_ttable;
 295
 296struct pt_regs fake_swapper_regs;
 297
 298extern void paging_init(void);
 299
 300void __init setup_arch(char **cmdline_p)
 301{
 302        int i;
 303        unsigned long highest_paddr;
 304
 305        sparc_ttable = (struct tt_entry *) &start;
 306
 307        /* Initialize PROM console and command line. */
 308        *cmdline_p = prom_getbootargs();
 309        strcpy(saved_command_line, *cmdline_p);
 310
 311        /* Set sparc_cpu_model */
 312        sparc_cpu_model = sun_unknown;
 313        if(!strcmp(&cputypval,"sun4 ")) { sparc_cpu_model=sun4; }
 314        if(!strcmp(&cputypval,"sun4c")) { sparc_cpu_model=sun4c; }
 315        if(!strcmp(&cputypval,"sun4m")) { sparc_cpu_model=sun4m; }
 316        if(!strcmp(&cputypval,"sun4s")) { sparc_cpu_model=sun4m; }  /* CP-1200 with PROM 2.30 -E */
 317        if(!strcmp(&cputypval,"sun4d")) { sparc_cpu_model=sun4d; }
 318        if(!strcmp(&cputypval,"sun4e")) { sparc_cpu_model=sun4e; }
 319        if(!strcmp(&cputypval,"sun4u")) { sparc_cpu_model=sun4u; }
 320
 321#ifdef CONFIG_SUN4
 322        if (sparc_cpu_model != sun4) {
 323                prom_printf("This kernel is for Sun4 architecture only.\n");
 324                prom_halt();
 325        }
 326#endif
 327        printk("ARCH: ");
 328        switch(sparc_cpu_model) {
 329        case sun4:
 330                printk("SUN4\n");
 331                break;
 332        case sun4c:
 333                printk("SUN4C\n");
 334                break;
 335        case sun4m:
 336                printk("SUN4M\n");
 337                break;
 338        case sun4d:
 339                printk("SUN4D\n");
 340                break;
 341        case sun4e:
 342                printk("SUN4E\n");
 343                break;
 344        case sun4u:
 345                printk("SUN4U\n");
 346                break;
 347        default:
 348                printk("UNKNOWN!\n");
 349                break;
 350        };
 351
 352#ifdef CONFIG_DUMMY_CONSOLE
 353        conswitchp = &dummy_con;
 354#elif defined(CONFIG_PROM_CONSOLE)
 355        conswitchp = &prom_con;
 356#endif
 357        boot_flags_init(*cmdline_p);
 358
 359        idprom_init();
 360        if (ARCH_SUN4C_SUN4)
 361                sun4c_probe_vac();
 362        load_mmu();
 363        (void) prom_probe_memory();
 364
 365        phys_base = 0xffffffffUL;
 366        highest_paddr = 0UL;
 367        for (i = 0; sp_banks[i].num_bytes != 0; i++) {
 368                unsigned long top;
 369
 370                if (sp_banks[i].base_addr < phys_base)
 371                        phys_base = sp_banks[i].base_addr;
 372                top = sp_banks[i].base_addr +
 373                        sp_banks[i].num_bytes;
 374                if (highest_paddr < top)
 375                        highest_paddr = top;
 376        }
 377
 378        if (!root_flags)
 379                root_mountflags &= ~MS_RDONLY;
 380        ROOT_DEV = to_kdev_t(root_dev);
 381#ifdef CONFIG_BLK_DEV_INITRD
 382        rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK;
 383        rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
 384        rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);     
 385#endif
 386
 387        prom_setsync(prom_sync_me);
 388
 389        {
 390#if !CONFIG_SUN_SERIAL
 391                serial_console = 0;
 392#else
 393                switch (console_fb) {
 394                case 0: /* Let get our io devices from prom */
 395                        {
 396                                int idev = prom_query_input_device();
 397                                int odev = prom_query_output_device();
 398                                if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) {
 399                                        serial_console = 0;
 400                                } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) {
 401                                        serial_console = 1;
 402                                } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) {
 403                                        serial_console = 2;
 404                                } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OTTYA) {
 405                                        prom_printf("MrCoffee ttya\n");
 406                                        serial_console = 1;
 407                                } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OSCREEN) {
 408                                        serial_console = 0;
 409                                        prom_printf("MrCoffee keyboard\n");
 410                                } else {
 411                                        prom_printf("Inconsistent or unknown console\n");
 412                                        prom_printf("You cannot mix serial and non serial input/output devices\n");
 413                                        prom_halt();
 414                                }
 415                        }
 416                        break;
 417                case 1: serial_console = 0; break; /* Force one of the framebuffers as console */
 418                case 2: serial_console = 1; break; /* Force ttya as console */
 419                case 3: serial_console = 2; break; /* Force ttyb as console */
 420                }
 421#endif
 422        }
 423
 424        if ((boot_flags & BOOTME_KGDBA)) {
 425                rs_kgdb_hook(0);
 426        }
 427        if ((boot_flags & BOOTME_KGDBB)) {
 428                rs_kgdb_hook(1);
 429        }
 430
 431        if((boot_flags&BOOTME_DEBUG) && (linux_dbvec!=0) && 
 432           ((*(short *)linux_dbvec) != -1)) {
 433                printk("Booted under KADB. Syncing trap table.\n");
 434                (*(linux_dbvec->teach_debugger))();
 435        }
 436        if((boot_flags & BOOTME_KGDB)) {
 437                set_debug_traps();
 438                prom_printf ("Breakpoint!\n");
 439                breakpoint();
 440        }
 441
 442        init_mm.context = (unsigned long) NO_CONTEXT;
 443        init_task.thread.kregs = &fake_swapper_regs;
 444
 445        if (serial_console)
 446                conswitchp = NULL;
 447
 448        paging_init();
 449}
 450
 451asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
 452{
 453        return -EIO;
 454}
 455
 456extern char *sparc_cpu_type[];
 457extern char *sparc_fpu_type[];
 458
 459static int show_cpuinfo(struct seq_file *m, void *__unused)
 460{
 461        int cpuid = hard_smp_processor_id();
 462
 463        seq_printf(m,
 464                   "cpu\t\t: %s\n"
 465                   "fpu\t\t: %s\n"
 466                   "promlib\t\t: Version %d Revision %d\n"
 467                   "prom\t\t: %d.%d\n"
 468                   "type\t\t: %s\n"
 469                   "ncpus probed\t: %d\n"
 470                   "ncpus active\t: %d\n"
 471#ifndef CONFIG_SMP
 472                   "BogoMips\t: %lu.%02lu\n"
 473#endif
 474                   ,
 475                   sparc_cpu_type[cpuid] ? : "undetermined",
 476                   sparc_fpu_type[cpuid] ? : "undetermined",
 477                   romvec->pv_romvers,
 478                   prom_rev,
 479                   romvec->pv_printrev >> 16,
 480                   (short) romvec->pv_printrev,
 481                   &cputypval,
 482                   linux_num_cpus,
 483                   smp_num_cpus
 484#ifndef CONFIG_SMP
 485                   , loops_per_jiffy/(500000/HZ),
 486                   (loops_per_jiffy/(5000/HZ)) % 100
 487#endif
 488                );
 489
 490#ifdef CONFIG_SMP
 491        smp_bogo_info(m);
 492#endif
 493        mmu_info(m);
 494#ifdef CONFIG_SMP
 495        smp_info(m);
 496#endif
 497        return 0;
 498}
 499
 500static void *c_start(struct seq_file *m, loff_t *pos)
 501{
 502        /* The pointer we are returning is arbitrary,
 503         * it just has to be non-NULL and not IS_ERR
 504         * in the success case.
 505         */
 506        return *pos == 0 ? &c_start : NULL;
 507}
 508
 509static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 510{
 511        ++*pos;
 512        return c_start(m, pos);
 513}
 514
 515static void c_stop(struct seq_file *m, void *v)
 516{
 517}
 518
 519struct seq_operations cpuinfo_op = {
 520        start:  c_start,
 521        next:   c_next,
 522        stop:   c_stop,
 523        show:   show_cpuinfo,
 524};
 525
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.