linux-old/arch/m68k/kernel/setup.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/m68k/kernel/setup.c
   3 *
   4 *  Copyright (C) 1995  Hamish Macdonald
   5 */
   6
   7/*
   8 * This file handles the architecture-dependent parts of system setup
   9 */
  10
  11#include <linux/config.h>
  12#include <linux/kernel.h>
  13#include <linux/mm.h>
  14#include <linux/sched.h>
  15#include <linux/delay.h>
  16#include <linux/interrupt.h>
  17#include <linux/fs.h>
  18#include <linux/console.h>
  19#include <linux/genhd.h>
  20#include <linux/errno.h>
  21#include <linux/string.h>
  22#include <linux/init.h>
  23#include <linux/bootmem.h>
  24#include <linux/seq_file.h>
  25#include <linux/module.h>
  26
  27#include <asm/bootinfo.h>
  28#include <asm/setup.h>
  29#include <asm/irq.h>
  30#include <asm/io.h>
  31#include <asm/machdep.h>
  32#ifdef CONFIG_AMIGA
  33#include <asm/amigahw.h>
  34#endif
  35#ifdef CONFIG_ATARI
  36#include <asm/atarihw.h>
  37#include <asm/atari_stram.h>
  38#endif
  39#ifdef CONFIG_SUN3X
  40#include <asm/dvma.h>
  41extern void sun_serial_setup(void);
  42#endif
  43
  44#ifdef CONFIG_BLK_DEV_INITRD
  45#include <linux/blk.h>
  46#endif
  47
  48unsigned long m68k_machtype;
  49unsigned long m68k_cputype;
  50unsigned long m68k_fputype;
  51unsigned long m68k_mmutype;
  52#ifdef CONFIG_VME
  53unsigned long vme_brdtype;
  54#endif
  55
  56int m68k_is040or060 = 0;
  57
  58extern int end;
  59extern unsigned long availmem;
  60
  61int m68k_num_memory = 0;
  62int m68k_realnum_memory = 0;
  63unsigned long m68k_memoffset;
  64struct mem_info m68k_memory[NUM_MEMINFO];
  65
  66static struct mem_info m68k_ramdisk = { 0, 0 };
  67
  68static char m68k_command_line[CL_SIZE];
  69char saved_command_line[CL_SIZE];
  70
  71char m68k_debug_device[6] = "";
  72
  73void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) __initdata = NULL;
  74/* machine dependent keyboard functions */
  75#ifdef CONFIG_VT
  76int (*mach_keyb_init) (void) __initdata = NULL;
  77int (*mach_kbdrate) (struct kbd_repeat *) = NULL;
  78void (*mach_kbd_leds) (unsigned int) = NULL;
  79int (*mach_kbd_translate)(unsigned char scancode, unsigned char *keycode, char raw_mode) = NULL;
  80#endif
  81/* machine dependent irq functions */
  82void (*mach_init_IRQ) (void) __initdata = NULL;
  83void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
  84void (*mach_get_model) (char *model) = NULL;
  85int (*mach_get_hardware_list) (char *buffer) = NULL;
  86int (*mach_get_irq_list) (char *) = NULL;
  87void (*mach_process_int) (int, struct pt_regs *) = NULL;
  88/* machine dependent timer functions */
  89unsigned long (*mach_gettimeoffset) (void);
  90void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
  91int (*mach_hwclk) (int, struct rtc_time*) = NULL;
  92int (*mach_set_clock_mmss) (unsigned long) = NULL;
  93unsigned int (*mach_get_ss)(void) = NULL;
  94int (*mach_get_rtc_pll)(struct rtc_pll_info *) = NULL;
  95int (*mach_set_rtc_pll)(struct rtc_pll_info *) = NULL;
  96void (*mach_reset)( void );
  97void (*mach_halt)( void ) = NULL;
  98void (*mach_power_off)( void ) = NULL;
  99long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
 100#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) 
 101void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
 102#endif
 103#ifdef CONFIG_HEARTBEAT
 104void (*mach_heartbeat) (int) = NULL;
 105EXPORT_SYMBOL(mach_heartbeat);
 106#endif
 107#ifdef CONFIG_M68K_L2_CACHE
 108void (*mach_l2_flush) (int) = NULL;
 109#endif
 110
 111#ifdef CONFIG_MAGIC_SYSRQ
 112unsigned int SYSRQ_KEY;
 113int mach_sysrq_key = -1;
 114int mach_sysrq_shift_state = 0;
 115int mach_sysrq_shift_mask = 0;
 116char *mach_sysrq_xlate = NULL;
 117#endif
 118
 119#if defined(CONFIG_ISA) && defined(MULTI_ISA)
 120int isa_type;
 121int isa_sex;
 122#endif
 123
 124extern int amiga_parse_bootinfo(const struct bi_record *);
 125extern int atari_parse_bootinfo(const struct bi_record *);
 126extern int mac_parse_bootinfo(const struct bi_record *);
 127extern int q40_parse_bootinfo(const struct bi_record *);
 128extern int bvme6000_parse_bootinfo(const struct bi_record *);
 129extern int mvme16x_parse_bootinfo(const struct bi_record *);
 130extern int mvme147_parse_bootinfo(const struct bi_record *);
 131
 132extern void config_amiga(void);
 133extern void config_atari(void);
 134extern void config_mac(void);
 135extern void config_sun3(void);
 136extern void config_apollo(void);
 137extern void config_mvme147(void);
 138extern void config_mvme16x(void);
 139extern void config_bvme6000(void);
 140extern void config_hp300(void);
 141extern void config_q40(void);
 142extern void config_sun3x(void);
 143
 144extern void mac_debugging_short (int, short);
 145extern void mac_debugging_long  (int, long);
 146
 147#define MASK_256K 0xfffc0000
 148
 149extern void paging_init(void);
 150
 151static void __init m68k_parse_bootinfo(const struct bi_record *record)
 152{
 153    while (record->tag != BI_LAST) {
 154        int unknown = 0;
 155        const unsigned long *data = record->data;
 156        switch (record->tag) {
 157            case BI_MACHTYPE:
 158            case BI_CPUTYPE:
 159            case BI_FPUTYPE:
 160            case BI_MMUTYPE:
 161                /* Already set up by head.S */
 162                break;
 163
 164            case BI_MEMCHUNK:
 165                if (m68k_num_memory < NUM_MEMINFO) {
 166                    m68k_memory[m68k_num_memory].addr = data[0];
 167                    m68k_memory[m68k_num_memory].size = data[1];
 168                    m68k_num_memory++;
 169                } else
 170                    printk("m68k_parse_bootinfo: too many memory chunks\n");
 171                break;
 172
 173            case BI_RAMDISK:
 174                m68k_ramdisk.addr = data[0];
 175                m68k_ramdisk.size = data[1];
 176                break;
 177
 178            case BI_COMMAND_LINE:
 179                strncpy(m68k_command_line, (const char *)data, CL_SIZE);
 180                m68k_command_line[CL_SIZE-1] = '\0';
 181                break;
 182
 183            default:
 184                if (MACH_IS_AMIGA)
 185                    unknown = amiga_parse_bootinfo(record);
 186                else if (MACH_IS_ATARI)
 187                    unknown = atari_parse_bootinfo(record);
 188                else if (MACH_IS_MAC)
 189                    unknown = mac_parse_bootinfo(record);
 190                else if (MACH_IS_Q40)
 191                    unknown = q40_parse_bootinfo(record);
 192                else if (MACH_IS_BVME6000)
 193                    unknown = bvme6000_parse_bootinfo(record);
 194                else if (MACH_IS_MVME16x)
 195                    unknown = mvme16x_parse_bootinfo(record);
 196                else if (MACH_IS_MVME147)
 197                    unknown = mvme147_parse_bootinfo(record);
 198                else
 199                    unknown = 1;
 200        }
 201        if (unknown)
 202            printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
 203                   record->tag);
 204        record = (struct bi_record *)((unsigned long)record+record->size);
 205    }
 206
 207    m68k_realnum_memory = m68k_num_memory;
 208#ifdef CONFIG_SINGLE_MEMORY_CHUNK
 209    if (m68k_num_memory > 1) {
 210        printk("Ignoring last %i chunks of physical memory\n",
 211               (m68k_num_memory - 1));
 212        m68k_num_memory = 1;
 213    }
 214    m68k_memoffset = m68k_memory[0].addr-PAGE_OFFSET;
 215#endif
 216}
 217
 218void __init setup_arch(char **cmdline_p)
 219{
 220        extern int _etext, _edata, _end;
 221#ifndef CONFIG_SUN3
 222        unsigned long endmem, startmem;
 223#endif
 224        int i;
 225        char *p, *q;
 226
 227        if (!MACH_IS_HP300) {
 228                /* The bootinfo is located right after the kernel bss */
 229                m68k_parse_bootinfo((const struct bi_record *)&_end);
 230        } else {
 231                /* FIXME HP300 doesn't use bootinfo yet */
 232                extern unsigned long hp300_phys_ram_base;
 233                unsigned long hp300_mem_size = 0xffffffff-hp300_phys_ram_base;
 234                m68k_cputype = CPU_68030;
 235                m68k_fputype = FPU_68882;
 236                m68k_memory[0].addr = hp300_phys_ram_base;
 237                /* 0.5M fudge factor */
 238                m68k_memory[0].size = hp300_mem_size-512*1024;
 239                m68k_num_memory++;
 240        }
 241
 242        if (CPU_IS_040)
 243                m68k_is040or060 = 4;
 244        else if (CPU_IS_060)
 245                m68k_is040or060 = 6;
 246
 247        /* FIXME: m68k_fputype is passed in by Penguin booter, which can
 248         * be confused by software FPU emulation. BEWARE.
 249         * We should really do our own FPU check at startup.
 250         * [what do we do with buggy 68LC040s? if we have problems
 251         *  with them, we should add a test to check_bugs() below] */
 252#ifndef CONFIG_M68KFPU_EMU_ONLY
 253        /* clear the fpu if we have one */
 254        if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
 255                volatile int zero = 0;
 256                asm __volatile__ ("frestore %0" : : "m" (zero));
 257        }
 258#endif  
 259
 260        init_mm.start_code = PAGE_OFFSET;
 261        init_mm.end_code = (unsigned long) &_etext;
 262        init_mm.end_data = (unsigned long) &_edata;
 263        init_mm.brk = (unsigned long) &_end;
 264
 265        *cmdline_p = m68k_command_line;
 266        memcpy(saved_command_line, *cmdline_p, CL_SIZE);
 267
 268        /* Parse the command line for arch-specific options.
 269         * For the m68k, this is currently only "debug=xxx" to enable printing
 270         * certain kernel messages to some machine-specific device.
 271         */
 272        for( p = *cmdline_p; p && *p; ) {
 273            i = 0;
 274            if (!strncmp( p, "debug=", 6 )) {
 275                strncpy( m68k_debug_device, p+6, sizeof(m68k_debug_device)-1 );
 276                m68k_debug_device[sizeof(m68k_debug_device)-1] = 0;
 277                if ((q = strchr( m68k_debug_device, ' ' ))) *q = 0;
 278                i = 1;
 279            }
 280#ifdef CONFIG_ATARI
 281            /* This option must be parsed very early */
 282            if (!strncmp( p, "switches=", 9 )) {
 283                extern void atari_switches_setup( const char *, int );
 284                atari_switches_setup( p+9, (q = strchr( p+9, ' ' )) ?
 285                                           (q - (p+9)) : strlen(p+9) );
 286                i = 1;
 287            }
 288#endif
 289
 290            if (i) {
 291                /* option processed, delete it */
 292                if ((q = strchr( p, ' ' )))
 293                    strcpy( p, q+1 );
 294                else
 295                    *p = 0;
 296            } else {
 297                if ((p = strchr( p, ' ' ))) ++p;
 298            }
 299        }
 300
 301        switch (m68k_machtype) {
 302#ifdef CONFIG_AMIGA
 303            case MACH_AMIGA:
 304                config_amiga();
 305                break;
 306#endif
 307#ifdef CONFIG_ATARI
 308            case MACH_ATARI:
 309                config_atari();
 310                break;
 311#endif
 312#ifdef CONFIG_MAC
 313            case MACH_MAC:
 314                config_mac();
 315                break;
 316#endif
 317#ifdef CONFIG_SUN3
 318            case MACH_SUN3:
 319                config_sun3();
 320                break;
 321#endif
 322#ifdef CONFIG_APOLLO
 323            case MACH_APOLLO:
 324                config_apollo();
 325                break;
 326#endif
 327#ifdef CONFIG_MVME147
 328            case MACH_MVME147:
 329                config_mvme147();
 330                break;
 331#endif
 332#ifdef CONFIG_MVME16x
 333            case MACH_MVME16x:
 334                config_mvme16x();
 335                break;
 336#endif
 337#ifdef CONFIG_BVME6000
 338            case MACH_BVME6000:
 339                config_bvme6000();
 340                break;
 341#endif
 342#ifdef CONFIG_HP300
 343            case MACH_HP300:
 344                config_hp300();
 345                break;
 346#endif
 347#ifdef CONFIG_Q40
 348            case MACH_Q40:
 349                config_q40();
 350                break;
 351#endif
 352#ifdef CONFIG_SUN3X
 353            case MACH_SUN3X:
 354                config_sun3x();
 355                break;
 356#endif
 357            default:
 358                panic ("No configuration setup");
 359        }
 360
 361#ifndef CONFIG_SUN3
 362        startmem= m68k_memory[0].addr;
 363        endmem = startmem + m68k_memory[0].size;
 364        high_memory = PAGE_OFFSET;
 365        for (i = 0; i < m68k_num_memory; i++) {
 366                m68k_memory[i].size &= MASK_256K;
 367                if (m68k_memory[i].addr < startmem)
 368                        startmem = m68k_memory[i].addr;
 369                if (m68k_memory[i].addr+m68k_memory[i].size > endmem)
 370                        endmem = m68k_memory[i].addr+m68k_memory[i].size;
 371                high_memory += m68k_memory[i].size;
 372        }
 373
 374        availmem += init_bootmem_node(NODE_DATA(0), availmem >> PAGE_SHIFT,
 375                                      startmem >> PAGE_SHIFT, endmem >> PAGE_SHIFT);
 376
 377        for (i = 0; i < m68k_num_memory; i++)
 378                free_bootmem(m68k_memory[i].addr, m68k_memory[i].size);
 379
 380        reserve_bootmem(m68k_memory[0].addr, availmem - m68k_memory[0].addr);
 381
 382#ifdef CONFIG_BLK_DEV_INITRD
 383        if (m68k_ramdisk.size) {
 384                reserve_bootmem(m68k_ramdisk.addr, m68k_ramdisk.size);
 385                initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
 386                initrd_end = initrd_start + m68k_ramdisk.size;
 387                printk ("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
 388        }
 389#endif
 390
 391#ifdef CONFIG_ATARI
 392        if (MACH_IS_ATARI)
 393                atari_stram_reserve_pages((void *)availmem);
 394#endif
 395#ifdef CONFIG_SUN3X
 396        if (MACH_IS_SUN3X) {
 397                dvma_init();
 398#ifdef CONFIG_SUN3X_ZS
 399                sun_serial_setup();
 400#endif
 401        }
 402#endif
 403
 404#endif /* !CONFIG_SUN3 */
 405
 406        paging_init();
 407
 408/* set ISA defs early as possible */
 409#if defined(CONFIG_ISA) && defined(MULTI_ISA)
 410#if defined(CONFIG_Q40) 
 411        if (MACH_IS_Q40) {
 412            isa_type = Q40_ISA;
 413            isa_sex = 0;
 414        } 
 415#elif defined(CONFIG_GG2)
 416        if (MACH_IS_AMIGA && AMIGAHW_PRESENT(GG2_ISA)){
 417            isa_type = GG2_ISA;
 418            isa_sex = 0;
 419        }
 420#elif defined(CONFIG_AMIGA_PCMCIA)
 421        if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)){
 422            isa_type = AG_ISA;
 423            isa_sex = 1;
 424        }
 425#endif
 426#endif
 427}
 428
 429static int show_cpuinfo(struct seq_file *m, void *v)
 430{
 431    const char *cpu, *mmu, *fpu;
 432    unsigned long clockfreq, clockfactor;
 433
 434#define LOOP_CYCLES_68020       (8)
 435#define LOOP_CYCLES_68030       (8)
 436#define LOOP_CYCLES_68040       (3)
 437#define LOOP_CYCLES_68060       (1)
 438
 439    if (CPU_IS_020) {
 440        cpu = "68020";
 441        clockfactor = LOOP_CYCLES_68020;
 442    } else if (CPU_IS_030) {
 443        cpu = "68030";
 444        clockfactor = LOOP_CYCLES_68030;
 445    } else if (CPU_IS_040) {
 446        cpu = "68040";
 447        clockfactor = LOOP_CYCLES_68040;
 448    } else if (CPU_IS_060) {
 449        cpu = "68060";
 450        clockfactor = LOOP_CYCLES_68060;
 451    } else {
 452        cpu = "680x0";
 453        clockfactor = 0;
 454    }
 455
 456#ifdef CONFIG_M68KFPU_EMU_ONLY
 457    fpu="none(soft float)";
 458#else
 459    if (m68k_fputype & FPU_68881)
 460        fpu = "68881";
 461    else if (m68k_fputype & FPU_68882)
 462        fpu = "68882";
 463    else if (m68k_fputype & FPU_68040)
 464        fpu = "68040";
 465    else if (m68k_fputype & FPU_68060)
 466        fpu = "68060";
 467    else if (m68k_fputype & FPU_SUNFPA)
 468        fpu = "Sun FPA";
 469    else
 470        fpu = "none";
 471#endif
 472
 473    if (m68k_mmutype & MMU_68851)
 474        mmu = "68851";
 475    else if (m68k_mmutype & MMU_68030)
 476        mmu = "68030";
 477    else if (m68k_mmutype & MMU_68040)
 478        mmu = "68040";
 479    else if (m68k_mmutype & MMU_68060)
 480        mmu = "68060";
 481    else if (m68k_mmutype & MMU_SUN3)
 482        mmu = "Sun-3";
 483    else if (m68k_mmutype & MMU_APOLLO)
 484        mmu = "Apollo";
 485    else
 486        mmu = "unknown";
 487
 488    clockfreq = loops_per_jiffy*HZ*clockfactor;
 489
 490    seq_printf(m, "CPU:\t\t%s\n"
 491                   "MMU:\t\t%s\n"
 492                   "FPU:\t\t%s\n"
 493                   "Clocking:\t%lu.%1luMHz\n"
 494                   "BogoMips:\t%lu.%02lu\n"
 495                   "Calibration:\t%lu loops\n",
 496                   cpu, mmu, fpu,
 497                   clockfreq/1000000,(clockfreq/100000)%10,
 498                   loops_per_jiffy/(500000/HZ),(loops_per_jiffy/(5000/HZ))%100,
 499                   loops_per_jiffy);
 500    return 0;
 501}
 502
 503static void *c_start(struct seq_file *m, loff_t *pos)
 504{
 505        return *pos < 1 ? (void *)1 : NULL;
 506}
 507static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 508{
 509        ++*pos;
 510        return NULL;
 511}
 512static void c_stop(struct seq_file *m, void *v)
 513{
 514}
 515struct seq_operations cpuinfo_op = {
 516        start:  c_start,
 517        next:   c_next,
 518        stop:   c_stop,
 519        show:   show_cpuinfo,
 520};
 521
 522int get_hardware_list(char *buffer)
 523{
 524    int len = 0;
 525    char model[80];
 526    unsigned long mem;
 527    int i;
 528
 529    if (mach_get_model)
 530        mach_get_model(model);
 531    else
 532        strcpy(model, "Unknown m68k");
 533
 534    len += sprintf(buffer+len, "Model:\t\t%s\n", model);
 535    //len += get_cpuinfo(buffer+len);
 536    for (mem = 0, i = 0; i < m68k_num_memory; i++)
 537        mem += m68k_memory[i].size;
 538    len += sprintf(buffer+len, "System Memory:\t%ldK\n", mem>>10);
 539
 540    if (mach_get_hardware_list)
 541        len += mach_get_hardware_list(buffer+len);
 542
 543    return(len);
 544}
 545
 546
 547#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY)
 548void __init floppy_setup(char *str, int *ints)
 549{
 550        if (mach_floppy_setup)
 551                mach_floppy_setup (str, ints);
 552}
 553
 554#endif
 555
 556/* for "kbd-reset" cmdline param */
 557void __init kbd_reset_setup(char *str, int *ints)
 558{
 559}
 560
 561void arch_gettod(int *year, int *mon, int *day, int *hour,
 562                 int *min, int *sec)
 563{
 564        if (mach_gettod)
 565                mach_gettod(year, mon, day, hour, min, sec);
 566        else
 567                *year = *mon = *day = *hour = *min = *sec = 0;
 568}
 569
 570void check_bugs(void)
 571{
 572#ifndef CONFIG_M68KFPU_EMU
 573        if (m68k_fputype == 0) {
 574                printk( KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
 575                                "WHICH IS REQUIRED BY LINUX/M68K ***\n" );
 576                printk( KERN_EMERG "Upgrade your hardware or join the FPU "
 577                                "emulation project\n" );
 578                printk( KERN_EMERG "(see http://no-fpu.linux-m68k.org)\n" );
 579                panic( "no FPU" );
 580        }
 581
 582#endif /* CONFIG_SUN3 */
 583
 584}
 585
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.