linux-old/arch/sh/kernel/setup.c
<<
>>
Prefs
   1/* $Id: setup.c,v 1.1.1.1.2.7 2003/06/20 13:13:25 trent Exp $
   2 *
   3 *  linux/arch/sh/kernel/setup.c
   4 *
   5 *  Copyright (C) 1999  Niibe Yutaka
   6 *
   7 */
   8
   9/*
  10 * This file handles the architecture-dependent parts of initialization
  11 */
  12
  13#include <linux/errno.h>
  14#include <linux/sched.h>
  15#include <linux/kernel.h>
  16#include <linux/mm.h>
  17#include <linux/stddef.h>
  18#include <linux/unistd.h>
  19#include <linux/ptrace.h>
  20#include <linux/slab.h>
  21#include <linux/user.h>
  22#include <linux/a.out.h>
  23#include <linux/tty.h>
  24#include <linux/ioport.h>
  25#include <linux/delay.h>
  26#include <linux/config.h>
  27#include <linux/init.h>
  28#ifdef CONFIG_BLK_DEV_RAM
  29#include <linux/blk.h>
  30#endif
  31#include <linux/bootmem.h>
  32#include <linux/console.h>
  33#include <linux/ctype.h>
  34#include <linux/seq_file.h>
  35#include <asm/processor.h>
  36#include <asm/page.h>
  37#include <asm/pgtable.h>
  38#include <asm/uaccess.h>
  39#include <asm/system.h>
  40#include <asm/io.h>
  41#include <asm/io_generic.h>
  42#include <asm/machvec.h>
  43#ifdef CONFIG_SH_EARLY_PRINTK
  44#include <asm/sh_bios.h>
  45#endif
  46
  47#ifdef CONFIG_SH_KGDB
  48#include <asm/kgdb.h>
  49static int kgdb_parse_options(char *options);
  50#endif
  51
  52/*
  53 * Machine setup..
  54 */
  55
  56/*
  57 * Initialize loops_per_jiffy as 10000000 (1000MIPS).
  58 * This value will be used at the very early stage of serial setup.
  59 * The bigger value means no problem.
  60 */
  61struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 0, 10000000, };
  62struct screen_info screen_info;
  63unsigned char aux_device_present = 0xaa;
  64
  65#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN)
  66struct sh_machine_vector sh_mv;
  67#endif
  68
  69/* We need this to satisfy some external references. */
  70struct screen_info screen_info = {
  71        0, 25,                  /* orig-x, orig-y */
  72        0,                      /* unused */
  73        0,                      /* orig-video-page */
  74        0,                      /* orig-video-mode */
  75        80,                     /* orig-video-cols */
  76        0,0,0,                  /* ega_ax, ega_bx, ega_cx */
  77        25,                     /* orig-video-lines */
  78        0,                      /* orig-video-isVGA */
  79        16                      /* orig-video-points */
  80};
  81
  82extern void fpu_init(void);
  83extern int root_mountflags;
  84extern int _text, _etext, _edata, _end;
  85
  86#define MV_NAME_SIZE 32
  87
  88static struct sh_machine_vector* __init get_mv_byname(const char* name);
  89
  90/*
  91 * This is set up by the setup-routine at boot-time
  92 */
  93#define PARAM   ((unsigned char *)empty_zero_page)
  94
  95#define MOUNT_ROOT_RDONLY (*(unsigned long *) (PARAM+0x000))
  96#define RAMDISK_FLAGS (*(unsigned long *) (PARAM+0x004))
  97#define ORIG_ROOT_DEV (*(unsigned long *) (PARAM+0x008))
  98#define LOADER_TYPE (*(unsigned long *) (PARAM+0x00c))
  99#define INITRD_START (*(unsigned long *) (PARAM+0x010))
 100#define INITRD_SIZE (*(unsigned long *) (PARAM+0x014))
 101/* ... */
 102#define COMMAND_LINE ((char *) (PARAM+0x100))
 103#define COMMAND_LINE_SIZE 256
 104
 105#define RAMDISK_IMAGE_START_MASK        0x07FF
 106#define RAMDISK_PROMPT_FLAG             0x8000
 107#define RAMDISK_LOAD_FLAG               0x4000  
 108
 109static char command_line[COMMAND_LINE_SIZE] = { 0, };
 110       char saved_command_line[COMMAND_LINE_SIZE];
 111
 112struct resource standard_io_resources[] = {
 113        { "dma1", 0x00, 0x1f },
 114        { "pic1", 0x20, 0x3f },
 115        { "timer", 0x40, 0x5f },
 116        { "keyboard", 0x60, 0x6f },
 117        { "dma page reg", 0x80, 0x8f },
 118        { "pic2", 0xa0, 0xbf },
 119        { "dma2", 0xc0, 0xdf },
 120        { "fpu", 0xf0, 0xff }
 121};
 122
 123#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
 124
 125/* System RAM - interrupted by the 640kB-1M hole */
 126#define code_resource (ram_resources[3])
 127#define data_resource (ram_resources[4])
 128static struct resource ram_resources[] = {
 129        { "System RAM", 0x000000, 0x09ffff, IORESOURCE_BUSY },
 130        { "System RAM", 0x100000, 0x100000, IORESOURCE_BUSY },
 131        { "Video RAM area", 0x0a0000, 0x0bffff },
 132        { "Kernel code", 0x100000, 0 },
 133        { "Kernel data", 0, 0 }
 134};
 135
 136unsigned long memory_start, memory_end;
 137
 138#ifdef CONFIG_SH_EARLY_PRINTK
 139/*
 140 *      Print a string through the BIOS
 141 */
 142static void sh_console_write(struct console *co, const char *s,
 143                                 unsigned count)
 144{
 145        sh_bios_console_write(s, count);
 146}
 147
 148static kdev_t sh_console_device(struct console *c)
 149{
 150        /* TODO: this is totally bogus */
 151        /* return MKDEV(SCI_MAJOR, SCI_MINOR_START + c->index); */
 152        return 0;
 153}
 154
 155/*
 156 *      Setup initial baud/bits/parity. We do two things here:
 157 *      - construct a cflag setting for the first rs_open()
 158 *      - initialize the serial port
 159 *      Return non-zero if we didn't find a serial port.
 160 */
 161static int __init sh_console_setup(struct console *co, char *options)
 162{
 163        int     cflag = CREAD | HUPCL | CLOCAL;
 164
 165        /*
 166         *      Now construct a cflag setting.
 167         *      TODO: this is a totally bogus cflag, as we have
 168         *      no idea what serial settings the BIOS is using, or
 169         *      even if its using the serial port at all.
 170         */
 171        cflag |= B115200 | CS8 | /*no parity*/0;
 172
 173        co->cflag = cflag;
 174
 175        return 0;
 176}
 177
 178static struct console sh_console = {
 179        name:           "bios",
 180        write:          sh_console_write,
 181        device:         sh_console_device,
 182        setup:          sh_console_setup,
 183        flags:          CON_PRINTBUFFER,
 184        index:          -1,
 185};
 186
 187void sh_console_init(void)
 188{
 189        register_console(&sh_console);
 190}
 191
 192void sh_console_unregister(void)
 193{
 194        unregister_console(&sh_console);
 195}
 196
 197#endif
 198
 199static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
 200                                  struct sh_machine_vector** mvp,
 201                                  unsigned long *mv_io_base,
 202                                  int *mv_mmio_enable)
 203{
 204        char c = ' ', *to = command_line, *from = COMMAND_LINE;
 205        int len = 0;
 206
 207        /* Save unparsed command line copy for /proc/cmdline */
 208        memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
 209        saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
 210
 211        memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START;
 212        memory_end = memory_start + __MEMORY_SIZE;
 213
 214        for (;;) {
 215                /*
 216                 * "mem=XXX[kKmM]" defines a size of memory.
 217                 */
 218                if (c == ' ' && !memcmp(from, "mem=", 4)) {
 219                        if (to != command_line)
 220                                to--;
 221                        {
 222                                unsigned long mem_size;
 223
 224                                mem_size = memparse(from+4, &from);
 225                                memory_end = memory_start + mem_size;
 226                        }
 227                }
 228                if (c == ' ' && !memcmp(from, "sh_mv=", 6)) {
 229                        char* mv_end;
 230                        char* mv_comma;
 231                        int mv_len;
 232                        if (to != command_line)
 233                                to--;
 234                        from += 6;
 235                        mv_end = strchr(from, ' ');
 236                        if (mv_end == NULL)
 237                                mv_end = from + strlen(from);
 238
 239                        mv_comma = strchr(from, ',');
 240                        if ((mv_comma != NULL) && (mv_comma < mv_end)) {
 241                                int ints[3];
 242                                get_options(mv_comma+1, ARRAY_SIZE(ints), ints);
 243                                *mv_io_base = ints[1];
 244                                *mv_mmio_enable = ints[2];
 245                                mv_len = mv_comma - from;
 246                        } else {
 247                                mv_len = mv_end - from;
 248                        }
 249                        if (mv_len > (MV_NAME_SIZE-1))
 250                                mv_len = MV_NAME_SIZE-1;
 251                        memcpy(mv_name, from, mv_len);
 252                        mv_name[mv_len] = '\0';
 253                        from = mv_end;
 254
 255                        *mvp = get_mv_byname(mv_name);
 256                }
 257                c = *(from++);
 258                if (!c)
 259                        break;
 260                if (COMMAND_LINE_SIZE <= ++len)
 261                        break;
 262                *(to++) = c;
 263        }
 264        *to = '\0';
 265        *cmdline_p = command_line;
 266}
 267
 268void __init setup_arch(char **cmdline_p)
 269{
 270#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN)
 271        extern struct sh_machine_vector mv_unknown;
 272#endif
 273        struct sh_machine_vector *mv = NULL;
 274        char mv_name[MV_NAME_SIZE] = "";
 275        unsigned long mv_io_base = 0;
 276        int mv_mmio_enable = 0;
 277        unsigned long bootmap_size;
 278        unsigned long start_pfn, max_pfn, max_low_pfn;
 279
 280#ifdef CONFIG_SH_EARLY_PRINTK
 281        sh_console_init();
 282#endif
 283        
 284        ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
 285
 286#ifdef CONFIG_BLK_DEV_RAM
 287        rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
 288        rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
 289        rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
 290#endif
 291
 292        if (!MOUNT_ROOT_RDONLY)
 293                root_mountflags &= ~MS_RDONLY;
 294        init_mm.start_code = (unsigned long)&_text;
 295        init_mm.end_code = (unsigned long) &_etext;
 296        init_mm.end_data = (unsigned long) &_edata;
 297        init_mm.brk = (unsigned long) &_end;
 298
 299        code_resource.start = virt_to_bus(&_text);
 300        code_resource.end = virt_to_bus(&_etext)-1;
 301        data_resource.start = virt_to_bus(&_etext);
 302        data_resource.end = virt_to_bus(&_edata)-1;
 303
 304        parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base, &mv_mmio_enable);
 305
 306#ifdef CONFIG_CMDLINE_BOOL
 307        sprintf(*cmdline_p, CONFIG_CMDLINE);
 308#endif
 309
 310#ifdef CONFIG_SH_GENERIC
 311        if (mv == NULL) {
 312                mv = &mv_unknown;
 313                if (*mv_name != '\0') {
 314                        printk("Warning: Unsupported machine %s, using unknown\n",
 315                               mv_name);
 316                }
 317        }
 318        sh_mv = *mv;
 319#endif
 320#ifdef CONFIG_SH_UNKNOWN
 321        sh_mv = mv_unknown;
 322#endif
 323
 324#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN)
 325        if (mv_io_base != 0) {
 326                sh_mv.mv_inb = generic_inb;
 327                sh_mv.mv_inw = generic_inw;
 328                sh_mv.mv_inl = generic_inl;
 329                sh_mv.mv_outb = generic_outb;
 330                sh_mv.mv_outw = generic_outw;
 331                sh_mv.mv_outl = generic_outl;
 332
 333                sh_mv.mv_inb_p = generic_inb_p;
 334                sh_mv.mv_inw_p = generic_inw_p;
 335                sh_mv.mv_inl_p = generic_inl_p;
 336                sh_mv.mv_outb_p = generic_outb_p;
 337                sh_mv.mv_outw_p = generic_outw_p;
 338                sh_mv.mv_outl_p = generic_outl_p;
 339
 340                sh_mv.mv_insb = generic_insb;
 341                sh_mv.mv_insw = generic_insw;
 342                sh_mv.mv_insl = generic_insl;
 343                sh_mv.mv_outsb = generic_outsb;
 344                sh_mv.mv_outsw = generic_outsw;
 345                sh_mv.mv_outsl = generic_outsl;
 346
 347                sh_mv.mv_isa_port2addr = generic_isa_port2addr;
 348                generic_io_base = mv_io_base;
 349        }
 350        if (mv_mmio_enable != 0) {
 351                sh_mv.mv_readb = generic_readb;
 352                sh_mv.mv_readw = generic_readw;
 353                sh_mv.mv_readl = generic_readl;
 354                sh_mv.mv_writeb = generic_writeb;
 355                sh_mv.mv_writew = generic_writew;
 356                sh_mv.mv_writel = generic_writel;
 357        }
 358#endif
 359
 360#define PFN_UP(x)       (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
 361#define PFN_DOWN(x)     ((x) >> PAGE_SHIFT)
 362#define PFN_PHYS(x)     ((x) << PAGE_SHIFT)
 363
 364#ifdef CONFIG_DISCONTIGMEM
 365        NODE_DATA(0)->bdata = &discontig_node_bdata[0];
 366        NODE_DATA(1)->bdata = &discontig_node_bdata[1];
 367
 368        bootmap_size = init_bootmem_node(NODE_DATA(1), 
 369                                         PFN_UP(__MEMORY_START_2ND),
 370                                         PFN_UP(__MEMORY_START_2ND),
 371                                         PFN_DOWN(__MEMORY_START_2ND+__MEMORY_SIZE_2ND));
 372        free_bootmem_node(NODE_DATA(1), __MEMORY_START_2ND, __MEMORY_SIZE_2ND);
 373        reserve_bootmem_node(NODE_DATA(1), __MEMORY_START_2ND, bootmap_size);
 374#endif
 375
 376        /*
 377         * Find the highest page frame number we have available
 378         */
 379        max_pfn = PFN_DOWN(__pa(memory_end));
 380
 381        /*
 382         * Determine low and high memory ranges:
 383         */
 384        max_low_pfn = max_pfn;
 385
 386        /*
 387         * Partially used pages are not usable - thus
 388         * we are rounding upwards:
 389         */
 390        start_pfn = PFN_UP(__pa(&_end));
 391        /*
 392         * Find a proper area for the bootmem bitmap. After this
 393         * bootstrap step all allocations (until the page allocator
 394         * is intact) must be done via bootmem_alloc().
 395         */
 396        bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
 397                                         __MEMORY_START>>PAGE_SHIFT,
 398                                         max_low_pfn);
 399
 400        /*
 401         * Register fully available low RAM pages with the bootmem allocator.
 402         */
 403        {
 404                unsigned long curr_pfn, last_pfn, pages;
 405
 406                /*
 407                 * We are rounding up the start address of usable memory:
 408                 */
 409                curr_pfn = PFN_UP(__MEMORY_START);
 410                /*
 411                 * ... and at the end of the usable range downwards:
 412                 */
 413                last_pfn = PFN_DOWN(__pa(memory_end));
 414
 415                if (last_pfn > max_low_pfn)
 416                        last_pfn = max_low_pfn;
 417
 418                pages = last_pfn - curr_pfn;
 419                free_bootmem_node(NODE_DATA(0), PFN_PHYS(curr_pfn),
 420                                  PFN_PHYS(pages));
 421        }
 422
 423        /*
 424         * Reserve the kernel text and
 425         * Reserve the bootmem bitmap. We do this in two steps (first step
 426         * was init_bootmem()), because this catches the (definitely buggy)
 427         * case of us accidentally initializing the bootmem allocator with
 428         * an invalid RAM area.
 429         */
 430        reserve_bootmem_node(NODE_DATA(0), __MEMORY_START+PAGE_SIZE,
 431                (PFN_PHYS(start_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START);
 432
 433        /*
 434         * reserve physical page 0 - it's a special BIOS page on many boxes,
 435         * enabling clean reboots, SMP operation, laptop functions.
 436         */
 437        reserve_bootmem_node(NODE_DATA(0), __MEMORY_START, PAGE_SIZE);
 438
 439#ifdef CONFIG_BLK_DEV_INITRD
 440        if (LOADER_TYPE && INITRD_START) {
 441                if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
 442                        reserve_bootmem_node(NODE_DATA(0), INITRD_START+__MEMORY_START, INITRD_SIZE);
 443                        initrd_start =
 444                                INITRD_START ? INITRD_START + PAGE_OFFSET + __MEMORY_START : 0;
 445                        initrd_end = initrd_start + INITRD_SIZE;
 446                } else {
 447                        printk("initrd extends beyond end of memory "
 448                            "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
 449                                    INITRD_START + INITRD_SIZE,
 450                                    max_low_pfn << PAGE_SHIFT);
 451                        initrd_start = 0;
 452                }
 453        }
 454#endif
 455
 456#if 0
 457        /*
 458         * Request the standard RAM and ROM resources -
 459         * they eat up PCI memory space
 460         */
 461        request_resource(&iomem_resource, ram_resources+0);
 462        request_resource(&iomem_resource, ram_resources+1);
 463        request_resource(&iomem_resource, ram_resources+2);
 464        request_resource(ram_resources+1, &code_resource);
 465        request_resource(ram_resources+1, &data_resource);
 466        probe_roms();
 467
 468        /* request I/O space for devices used on all i[345]86 PCs */
 469        for (i = 0; i < STANDARD_IO_RESOURCES; i++)
 470                request_resource(&ioport_resource, standard_io_resources+i);
 471#endif
 472
 473#ifdef CONFIG_VT
 474#if defined(CONFIG_VGA_CONSOLE)
 475        conswitchp = &vga_con;
 476#elif defined(CONFIG_DUMMY_CONSOLE)
 477        conswitchp = &dummy_con;
 478#endif
 479#endif
 480
 481        /* Perform the machine specific initialisation */
 482        if (sh_mv.mv_init_arch != NULL) {
 483                sh_mv.mv_init_arch();
 484        }
 485
 486#if defined(__SH4__)
 487        init_task.used_math = 0;
 488        init_task.flags &= ~PF_USEDFPU;
 489#endif
 490
 491#ifdef CONFIG_UBC_WAKEUP
 492        /*
 493         * Some brain-damaged loaders decided it would be a good idea to put
 494         * the UBC to sleep. This causes some issues when it comes to things
 495         * like PTRACE_SINGLESTEP or doing hardware watchpoints in GDB.  So ..
 496         * we wake it up and hope that all is well.
 497         */
 498        ubc_wakeup();
 499#endif
 500
 501        paging_init();
 502}
 503
 504struct sh_machine_vector* __init get_mv_byname(const char* name)
 505{
 506        extern int strcasecmp(const char *, const char *);
 507        extern long __machvec_start, __machvec_end;
 508        struct sh_machine_vector *all_vecs =
 509                (struct sh_machine_vector *)&__machvec_start;
 510
 511        int i, n = ((unsigned long)&__machvec_end
 512                    - (unsigned long)&__machvec_start)/
 513                sizeof(struct sh_machine_vector);
 514
 515        for (i = 0; i < n; ++i) {
 516                struct sh_machine_vector *mv = &all_vecs[i];
 517                if (mv == NULL)
 518                        continue;
 519                if (strcasecmp(name, mv->mv_name) == 0) {
 520                        return mv;
 521                }
 522        }
 523        return NULL;
 524}
 525
 526/*
 527 *      Get CPU information for use by the procfs.
 528 */
 529#ifdef CONFIG_PROC_FS
 530static int show_cpuinfo(struct seq_file *m, void *v)
 531{
 532#if defined(__sh3__)
 533        seq_printf(m, "cpu family\t: SH-3\n"
 534                      "cache size\t: 8K-byte\n");
 535#elif defined(__SH4__)
 536        seq_printf(m, "cpu family\t: SH-4\n"
 537                      "cache size\t: 8K-byte/16K-byte\n");
 538#endif
 539        seq_printf(m, "bogomips\t: %lu.%02lu\n\n",
 540                     loops_per_jiffy/(500000/HZ),
 541                     (loops_per_jiffy/(5000/HZ)) % 100);
 542        seq_printf(m, "Machine: %s\n", sh_mv.mv_name);
 543
 544#define PRINT_CLOCK(name, value) \
 545        seq_printf(m, name " clock: %d.%02dMHz\n", \
 546                     ((value) / 1000000), ((value) % 1000000)/10000)
 547        
 548        PRINT_CLOCK("CPU", boot_cpu_data.cpu_clock);
 549        PRINT_CLOCK("Bus", boot_cpu_data.bus_clock);
 550#ifdef CONFIG_CPU_SUBTYPE_ST40
 551        PRINT_CLOCK("Memory", boot_cpu_data.memory_clock);
 552#endif
 553        PRINT_CLOCK("Peripheral module", boot_cpu_data.module_clock);
 554
 555        return 0;
 556}
 557
 558static void *c_start(struct seq_file *m, loff_t *pos)
 559{
 560        return (void*)(*pos == 0);
 561}
 562static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 563{
 564        return NULL;
 565}
 566static void c_stop(struct seq_file *m, void *v)
 567{
 568}
 569struct seq_operations cpuinfo_op = {
 570        start:  c_start,
 571        next:   c_next,
 572        stop:   c_stop,
 573        show:   show_cpuinfo,
 574};
 575#endif /* CONFIG_PROC_FS */
 576
 577#ifdef CONFIG_SH_KGDB
 578/*
 579 * Parse command-line kgdb options.  By default KGDB is enabled,
 580 * entered on error (or other action) using default serial info.
 581 * The command-line option can include a serial port specification
 582 * and an action to override default or configured behavior.
 583 */
 584struct kgdb_sermap kgdb_sci_sermap =
 585{ "ttySC", 5, kgdb_sci_setup, NULL };
 586
 587struct kgdb_sermap *kgdb_serlist = &kgdb_sci_sermap;
 588struct kgdb_sermap *kgdb_porttype = &kgdb_sci_sermap;
 589
 590void kgdb_register_sermap(struct kgdb_sermap *map)
 591{
 592        struct kgdb_sermap *last;
 593
 594        for (last = kgdb_serlist; last->next; last = last->next)
 595                ;
 596        last->next = map;
 597        if (!map->namelen) {
 598                map->namelen = strlen(map->name);
 599        }
 600}
 601
 602static int __init kgdb_parse_options(char *options)
 603{
 604        char c;
 605        int baud;
 606
 607        /* Check for port spec (or use default) */
 608
 609        /* Determine port type and instance */
 610        if (!memcmp(options, "tty", 3)) {
 611                struct kgdb_sermap *map = kgdb_serlist;
 612
 613                while (map && memcmp(options, map->name, map->namelen))
 614                        map = map->next;
 615
 616                if (!map) {
 617                        KGDB_PRINTK("unknown port spec in %s\n", options);
 618                        return -1;
 619                }
 620
 621                kgdb_porttype = map;
 622                kgdb_serial_setup = map->setup_fn;
 623                kgdb_portnum = options[map->namelen] - '0';
 624                options += map->namelen + 1;
 625
 626                options = (*options == ',') ? options+1 : options;
 627                
 628                /* Read optional parameters (baud/parity/bits) */
 629                baud = simple_strtoul(options, &options, 10);
 630                if (baud != 0) {
 631                        kgdb_baud = baud;
 632
 633                        c = toupper(*options);
 634                        if (c == 'E' || c == 'O' || c == 'N') {
 635                                kgdb_parity = c;
 636                                options++;
 637                        }
 638
 639                        c = *options;
 640                        if (c == '7' || c == '8') {
 641                                kgdb_bits = c;
 642                                options++;
 643                        }
 644                        options = (*options == ',') ? options+1 : options;
 645                }
 646        }
 647
 648        /* Check for action specification */
 649        if (!memcmp(options, "halt", 4)) {
 650                kgdb_halt = 1;
 651                options += 4;
 652        } else if (!memcmp(options, "disabled", 8)) {
 653                kgdb_enabled = 0;
 654                options += 8;
 655        }
 656
 657        if (*options) {
 658                KGDB_PRINTK("ignored unknown options: %s\n", options);
 659                return 0;
 660        }
 661        return 1;
 662}
 663__setup("kgdb=", kgdb_parse_options);
 664#endif /* CONFIG_SH_KGDB */
 665
 666
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.