1/* 2 * linux/arch/alpha/kernel/setup.c 3 * 4 * Copyright (C) 1995 Linus Torvalds 5 */ 6 7/* 2.3.x bootmem, 1999 Andrea Arcangeli <andrea@suse.de> */ 8 9/* 10 * Bootup setup stuff. 11 */ 12 13#include <linux/sched.h> 14#include <linux/kernel.h> 15#include <linux/mm.h> 16#include <linux/stddef.h> 17#include <linux/unistd.h> 18#include <linux/ptrace.h> 19#include <linux/slab.h> 20#include <linux/user.h> 21#include <linux/a.out.h> 22#include <linux/tty.h> 23#include <linux/delay.h> 24#include <linux/config.h> /* CONFIG_ALPHA_LCA etc */ 25#include <linux/mc146818rtc.h> 26#include <linux/console.h> 27#include <linux/errno.h> 28#include <linux/init.h> 29#include <linux/string.h> 30#include <linux/ioport.h> 31#include <linux/bootmem.h> 32#include <linux/pci.h> 33#include <linux/seq_file.h> 34 35#ifdef CONFIG_BLK_DEV_INITRD 36#include <linux/blk.h> 37#endif 38 39#include <linux/notifier.h> 40extern struct notifier_block *panic_notifier_list; 41static int alpha_panic_event(struct notifier_block *, unsigned long, void *); 42static struct notifier_block alpha_panic_block = { 43 alpha_panic_event, 44 NULL, 45 INT_MAX /* try to do it first */ 46}; 47 48#include <asm/uaccess.h> 49#include <asm/pgtable.h> 50#include <asm/system.h> 51#include <asm/hwrpb.h> 52#include <asm/dma.h> 53#include <asm/io.h> 54#include <asm/mmu_context.h> 55#include <asm/console.h> 56 57#include "proto.h" 58#include "pci_impl.h" 59 60 61struct hwrpb_struct *hwrpb; 62unsigned long srm_hae; 63 64/* Which processor we booted from. */ 65int boot_cpuid; 66 67/* 68 * Using SRM callbacks for initial console output. This works from 69 * setup_arch() time through the end of time_init(), as those places 70 * are under our (Alpha) control. 71 72 * "srmcons" specified in the boot command arguments allows us to 73 * see kernel messages during the period of time before the true 74 * console device is "registered" during console_init(). As of this 75 * version (2.4.10), time_init() is the last Alpha-specific code 76 * called before console_init(), so we put "unregister" code 77 * there to prevent schizophrenic console behavior later... ;-} 78 * 79 * By default, OFF; set it with a bootcommand arg of "srmcons". 80 */ 81int srmcons_output = 0; 82 83/* Enforce a memory size limit; useful for testing. By default, none. */ 84unsigned long mem_size_limit = 0; 85 86#ifdef CONFIG_ALPHA_GENERIC 87struct alpha_machine_vector alpha_mv; 88int alpha_using_srm; 89#endif 90 91unsigned char aux_device_present = 0xaa; 92 93#define N(a) (sizeof(a)/sizeof(a[0])) 94 95static struct alpha_machine_vector *get_sysvec(long, long, long); 96static struct alpha_machine_vector *get_sysvec_byname(const char *); 97static void get_sysnames(long, long, long, char **, char **); 98 99static char command_line[COMMAND_LINE_SIZE]; 100char saved_command_line[COMMAND_LINE_SIZE]; 101 102/* 103 * The format of "screen_info" is strange, and due to early 104 * i386-setup code. This is just enough to make the console 105 * code think we're on a VGA color display. 106 */ 107 108struct screen_info screen_info = { 109 orig_x: 0, 110 orig_y: 25, 111 orig_video_cols: 80, 112 orig_video_lines: 25, 113 orig_video_isVGA: 1, 114 orig_video_points: 16 115}; 116 117/* 118 * The direct map I/O window, if any. This should be the same 119 * for all busses, since it's used by virt_to_bus. 120 */ 121 122unsigned long __direct_map_base; 123unsigned long __direct_map_size; 124 125/* 126 * Declare all of the machine vectors. 127 */ 128 129/* GCC 2.7.2 (on alpha at least) is lame. It does not support either 130 __attribute__((weak)) or #pragma weak. Bypass it and talk directly 131 to the assembler. */ 132 133#define WEAK(X) \ 134 extern struct alpha_machine_vector X; \ 135 asm(".weak "#X) 136 137WEAK(alcor_mv); 138WEAK(alphabook1_mv); 139WEAK(avanti_mv); 140WEAK(cabriolet_mv); 141WEAK(clipper_mv); 142WEAK(dp264_mv); 143WEAK(eb164_mv); 144WEAK(eb64p_mv); 145WEAK(eb66_mv); 146WEAK(eb66p_mv); 147WEAK(eiger_mv); 148WEAK(jensen_mv); 149WEAK(lx164_mv); 150WEAK(miata_mv); 151WEAK(mikasa_mv); 152WEAK(mikasa_primo_mv); 153WEAK(monet_mv); 154WEAK(nautilus_mv); 155WEAK(noname_mv); 156WEAK(noritake_mv); 157WEAK(noritake_primo_mv); 158WEAK(p2k_mv); 159WEAK(pc164_mv); 160WEAK(privateer_mv); 161WEAK(rawhide_mv); 162WEAK(ruffian_mv); 163WEAK(rx164_mv); 164WEAK(sable_mv); 165WEAK(sable_gamma_mv); 166WEAK(shark_mv); 167WEAK(sx164_mv); 168WEAK(takara_mv); 169WEAK(webbrick_mv); 170WEAK(wildfire_mv); 171WEAK(xl_mv); 172WEAK(xlt_mv); 173 174#undef WEAK 175 176/* 177 * I/O resources inherited from PeeCees. Except for perhaps the 178 * turbochannel alphas, everyone has these on some sort of SuperIO chip. 179 * 180 * ??? If this becomes less standard, move the struct out into the 181 * machine vector. 182 */ 183 184static void __init 185reserve_std_resources(void) 186{ 187 static struct resource standard_io_resources[] = { 188 { "rtc", -1, -1 }, 189 { "dma1", 0x00, 0x1f }, 190 { "pic1", 0x20, 0x3f }, 191 { "timer", 0x40, 0x5f }, 192 { "keyboard", 0x60, 0x6f }, 193 { "dma page reg", 0x80, 0x8f }, 194 { "pic2", 0xa0, 0xbf }, 195 { "dma2", 0xc0, 0xdf }, 196 }; 197 198 struct resource *io = &ioport_resource; 199 long i; 200 201 if (hose_head) { 202 struct pci_controller *hose; 203 for (hose = hose_head; hose; hose = hose->next) 204 if (hose->index == 0) { 205 io = hose->io_space; 206 break; 207 } 208 } 209 210 /* Fix up for the Jensen's queer RTC placement. */ 211 standard_io_resources[0].start = RTC_PORT(0); 212 standard_io_resources[0].end = RTC_PORT(0) + 0x10; 213 214 for (i = 0; i < N(standard_io_resources); ++i) 215 request_resource(io, standard_io_resources+i); 216} 217 218#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) 219#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) 220#define PFN_PHYS(x) ((x) << PAGE_SHIFT) 221#define PFN_MAX PFN_DOWN(0x80000000) 222#define for_each_mem_cluster(memdesc, cluster, i) \ 223 for ((cluster) = (memdesc)->cluster, (i) = 0; \ 224 (i) < (memdesc)->numclusters; (i)++, (cluster)++) 225 226static unsigned long __init 227get_mem_size_limit(char *s) 228{ 229 unsigned long end = 0; 230 char *from = s; 231 232 end = simple_strtoul(from, &from, 0); 233 if ( *from == 'K' || *from == 'k' ) { 234 end = end << 10; 235 from++; 236 } else if ( *from == 'M' || *from == 'm' ) { 237 end = end << 20; 238 from++; 239 } else if ( *from == 'G' || *from == 'g' ) { 240 end = end << 30; 241 from++; 242 } 243 return end >> PAGE_SHIFT; /* Return the PFN of the limit. */ 244} 245 246#ifndef CONFIG_DISCONTIGMEM 247static void __init 248setup_memory(void *kernel_end) 249{ 250 struct memclust_struct * cluster; 251 struct memdesc_struct * memdesc; 252 unsigned long start_kernel_pfn, end_kernel_pfn; 253 unsigned long bootmap_size, bootmap_pages, bootmap_start; 254 unsigned long start, end; 255 int i; 256 257 /* Find free clusters, and init and free the bootmem accordingly. */ 258 memdesc = (struct memdesc_struct *) 259 (hwrpb->mddt_offset + (unsigned long) hwrpb); 260 261 for_each_mem_cluster(memdesc, cluster, i) { 262 printk("memcluster %d, usage %01lx, start %8lu, end %8lu\n", 263 i, cluster->usage, cluster->start_pfn, 264 cluster->start_pfn + cluster->numpages); 265 266 /* Bit 0 is console/PALcode reserved. Bit 1 is 267 non-volatile memory -- we might want to mark 268 this for later. */ 269 if (cluster->usage & 3) 270 continue; 271 272 end = cluster->start_pfn + cluster->numpages; 273 if (end > max_low_pfn) 274 max_low_pfn = end; 275 } 276 277 if (mem_size_limit && max_low_pfn >= mem_size_limit) 278 { 279 printk("setup: forcing memory size to %ldK (from %ldK).\n", 280 mem_size_limit << (PAGE_SHIFT - 10), 281 max_low_pfn << (PAGE_SHIFT - 10)); 282 max_low_pfn = mem_size_limit; 283 } 284 285 /* Find the bounds of kernel memory. */ 286 start_kernel_pfn = PFN_DOWN(KERNEL_START_PHYS); 287 end_kernel_pfn = PFN_UP(virt_to_phys(kernel_end)); 288 bootmap_start = -1; 289 290 try_again: 291 if (max_low_pfn <= end_kernel_pfn) 292 panic("not enough memory to boot"); 293 294 /* We need to know how many physically contiguous pages 295 we'll need for the bootmap. */ 296 bootmap_pages = bootmem_bootmap_pages(max_low_pfn); 297 298 /* Now find a good region where to allocate the bootmap. */ 299 for_each_mem_cluster(memdesc, cluster, i) { 300 if (cluster->usage & 3) 301 continue; 302 303 start = cluster->start_pfn; 304 end = start + cluster->numpages; 305 if (start >= max_low_pfn) 306 continue; 307 if (end > max_low_pfn) 308 end = max_low_pfn; 309 if (start < start_kernel_pfn) { 310 if (end > end_kernel_pfn 311 && end - end_kernel_pfn >= bootmap_pages) { 312 bootmap_start = end_kernel_pfn; 313 break; 314 } else if (end > start_kernel_pfn) 315 end = start_kernel_pfn; 316 } else if (start < end_kernel_pfn) 317 start = end_kernel_pfn; 318 if (end - start >= bootmap_pages) { 319 bootmap_start = start; 320 break; 321 } 322 } 323 324 if (bootmap_start == -1) { 325 max_low_pfn >>= 1; 326 goto try_again; 327 } 328 329 /* Allocate the bootmap and mark the whole MM as reserved. */ 330 bootmap_size = init_bootmem(bootmap_start, max_low_pfn); 331 332 /* Mark the free regions. */ 333 for_each_mem_cluster(memdesc, cluster, i) { 334 if (cluster->usage & 3) 335 continue; 336 337 start = cluster->start_pfn; 338 end = cluster->start_pfn + cluster->numpages; 339 if (start >= max_low_pfn) 340 continue; 341 if (end > max_low_pfn) 342 end = max_low_pfn; 343 if (start < start_kernel_pfn) { 344 if (end > end_kernel_pfn) { 345 free_bootmem(PFN_PHYS(start), 346 (PFN_PHYS(start_kernel_pfn) 347 - PFN_PHYS(start))); 348 printk("freeing pages %ld:%ld\n", 349 start, start_kernel_pfn); 350 start = end_kernel_pfn; 351 } else if (end > start_kernel_pfn) 352 end = start_kernel_pfn; 353 } else if (start < end_kernel_pfn) 354 start = end_kernel_pfn; 355 if (start >= end) 356 continue; 357 358 free_bootmem(PFN_PHYS(start), PFN_PHYS(end) - PFN_PHYS(start)); 359 printk("freeing pages %ld:%ld\n", start, end); 360 } 361 362 /* Reserve the bootmap memory. */ 363 reserve_bootmem(PFN_PHYS(bootmap_start), bootmap_size); 364 printk("reserving pages %ld:%ld\n", bootmap_start, bootmap_start+PFN_UP(bootmap_size)); 365 366#ifdef CONFIG_BLK_DEV_INITRD 367 initrd_start = INITRD_START; 368 if (initrd_start) { 369 initrd_end = initrd_start+INITRD_SIZE; 370 printk("Initial ramdisk at: 0x%p (%lu bytes)\n", 371 (void *) initrd_start, INITRD_SIZE); 372 373 if ((void *)initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) { 374 printk("initrd extends beyond end of memory " 375 "(0x%08lx > 0x%p)\ndisabling initrd\n", 376 initrd_end, 377 phys_to_virt(PFN_PHYS(max_low_pfn))); 378 initrd_start = initrd_end = 0; 379 } else { 380 reserve_bootmem(virt_to_phys((void *)initrd_start), 381 INITRD_SIZE); 382 } 383 } 384#endif /* CONFIG_BLK_DEV_INITRD */ 385} 386#else 387extern void setup_memory(void *); 388#endif /* !CONFIG_DISCONTIGMEM */ 389 390int __init 391page_is_ram(unsigned long pfn) 392{ 393 struct memclust_struct * cluster; 394 struct memdesc_struct * memdesc; 395 int i; 396 397 memdesc = (struct memdesc_struct *) 398 (hwrpb->mddt_offset + (unsigned long) hwrpb); 399 for_each_mem_cluster(memdesc, cluster, i) 400 { 401 if (pfn >= cluster->start_pfn && 402 pfn < cluster->start_pfn + cluster->numpages) { 403 return (cluster->usage & 3) ? 0 : 1; 404 } 405 } 406 407 return 0; 408} 409 410#undef PFN_UP 411#undef PFN_DOWN 412#undef PFN_PHYS 413#undef PFN_MAX 414 415#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM) 416/* 417 * Manage the SRM callbacks as a "console". 418 */ 419static struct console srmcons; 420 421void __init register_srm_console(void) 422{ 423 register_console(&srmcons); 424} 425 426void __init unregister_srm_console(void) 427{ 428 unregister_console(&srmcons); 429} 430 431static void srm_console_write(struct console *co, const char *s, 432 unsigned count) 433{ 434 srm_printk(s); 435} 436 437static kdev_t srm_console_device(struct console *c) 438{ 439 /* Huh? */ 440 return MKDEV(TTY_MAJOR, 64 + c->index); 441} 442 443static int __init srm_console_setup(struct console *co, char *options) 444{ 445 return 1; 446} 447 448static struct console srmcons = { 449 name: "srm0", 450 write: srm_console_write, 451 device: srm_console_device, 452 setup: srm_console_setup, 453 flags: CON_PRINTBUFFER | CON_ENABLED, /* fake it out */ 454 index: -1, 455}; 456 457#else 458void __init register_srm_console(void) 459{ 460} 461void __init unregister_srm_console(void) 462{ 463} 464#endif 465 466void __init 467setup_arch(char **cmdline_p) 468{ 469 extern char _end[]; 470 471 struct alpha_machine_vector *vec = NULL; 472 struct percpu_struct *cpu; 473 char *type_name, *var_name, *p; 474 void *kernel_end = _end; /* end of kernel */ 475 476 hwrpb = (struct hwrpb_struct*) __va(INIT_HWRPB->phys_addr); 477 boot_cpuid = hard_smp_processor_id(); 478 479 /* Register a call for panic conditions. */ 480 notifier_chain_register(&panic_notifier_list, &alpha_panic_block); 481 482#ifdef CONFIG_ALPHA_GENERIC 483 /* Assume that we've booted from SRM if we havn't booted from MILO. 484 Detect the later by looking for "MILO" in the system serial nr. */ 485 alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0; 486#endif 487 488 /* If we are using SRM, we want to allow callbacks 489 as early as possible, so do this NOW, and then 490 they should work immediately thereafter. 491 */ 492 kernel_end = callback_init(kernel_end); 493 494 /* 495 * Locate the command line. 496 */ 497 /* Hack for Jensen... since we're restricted to 8 or 16 chars for 498 boot flags depending on the boot mode, we need some shorthand. 499 This should do for installation. */ 500 if (strcmp(COMMAND_LINE, "INSTALL") == 0) { 501 strcpy(command_line, "root=/dev/fd0 load_ramdisk=1"); 502 } else { 503 strncpy(command_line, COMMAND_LINE, sizeof command_line); 504 command_line[sizeof(command_line)-1] = 0; 505 } 506 strcpy(saved_command_line, command_line); 507 *cmdline_p = command_line; 508 509 /* 510 * Process command-line arguments. 511 */ 512 for (p = strtok(command_line, " \t"); p ; p = strtok(NULL, " \t")) { 513 if (strncmp(p, "alpha_mv=", 9) == 0) { 514 vec = get_sysvec_byname(p+9); 515 continue; 516 } 517 if (strncmp(p, "cycle=", 6) == 0) { 518 est_cycle_freq = simple_strtol(p+6, NULL, 0); 519 continue; 520 } 521 if (strncmp(p, "mem=", 4) == 0) { 522 mem_size_limit = get_mem_size_limit(p+4); 523 continue; 524 } 525 if (strncmp(p, "srmcons", 7) == 0) { 526 srmcons_output = 1; 527 continue; 528 } 529 } 530 531 /* Replace the command line, now that we've killed it with strtok. */ 532 strcpy(command_line, saved_command_line); 533 534 /* If we want SRM console printk echoing early, do it now. */ 535 if (alpha_using_srm && srmcons_output) { 536 register_srm_console(); 537 } 538 539 /* 540 * Indentify and reconfigure for the current system. 541 */ 542 cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset); 543 544 get_sysnames(hwrpb->sys_type, hwrpb->sys_variation, 545 cpu->type, &type_name, &var_name); 546 if (*var_name == '0') 547 var_name = ""; 548 549 if (!vec) { 550 vec = get_sysvec(hwrpb->sys_type, hwrpb->sys_variation, 551 cpu->type); 552 } 553 554 if (!vec) { 555 panic("Unsupported system type: %s%s%s (%ld %ld)\n", 556 type_name, (*var_name ? " variation " : ""), var_name, 557 hwrpb->sys_type, hwrpb->sys_variation); 558 } 559 if (vec != &alpha_mv) { 560 alpha_mv = *vec; 561 } 562 563 printk("Booting " 564#ifdef CONFIG_ALPHA_GENERIC 565 "GENERIC " 566#endif 567 "on %s%s%s using machine vector %s from %s\n", 568 type_name, (*var_name ? " variation " : ""), 569 var_name, alpha_mv.vector_name, 570 (alpha_using_srm ? "SRM" : "MILO")); 571 572 printk("Command line: %s\n", command_line); 573 574 /* 575 * Sync up the HAE. 576 * Save the SRM's current value for restoration. 577 */ 578 srm_hae = *alpha_mv.hae_register; 579 __set_hae(alpha_mv.hae_cache); 580 581 /* Reset enable correctable error reports. */ 582 wrmces(0x7); 583 584 /* Find our memory. */ 585 setup_memory(kernel_end); 586 587 /* Initialize the machine. Usually has to do with setting up 588 DMA windows and the like. */ 589 if (alpha_mv.init_arch) 590 alpha_mv.init_arch(); 591 592 /* Reserve standard resources. */ 593 reserve_std_resources(); 594 595 /* 596 * Give us a default console. TGA users will see nothing until 597 * chr_dev_init is called, rather late in the boot sequence. 598 */ 599 600#ifdef CONFIG_VT 601#if defined(CONFIG_VGA_CONSOLE) 602 conswitchp = &vga_con; 603#elif defined(CONFIG_DUMMY_CONSOLE) 604 conswitchp = &dummy_con; 605#endif 606#endif 607 608 /* Default root filesystem to sda2. */ 609 ROOT_DEV = to_kdev_t(0x0802); 610 611 612 if (hwrpb->max_asn != MAX_ASN) { 613 printk("Max ASN from HWRPB is bad (0x%lx)\n", hwrpb->max_asn); 614 } 615 616 /* 617 * Identify the flock of penguins. 618 */ 619 620#ifdef CONFIG_SMP 621 setup_smp(); 622#endif 623 paging_init(); 624} 625 626static char sys_unknown[] = "Unknown"; 627static char systype_names[][16] = { 628 "0", 629 "ADU", "Cobra", "Ruby", "Flamingo", "Mannequin", "Jensen", 630 "Pelican", "Morgan", "Sable", "Medulla", "Noname", 631 "Turbolaser", "Avanti", "Mustang", "Alcor", "Tradewind", 632 "Mikasa", "EB64", "EB66", "EB64+", "AlphaBook1", 633 "Rawhide", "K2", "Lynx", "XL", "EB164", "Noritake", 634 "Cortex", "29", "Miata", "XXM", "Takara", "Yukon", 635 "Tsunami", "Wildfire", "CUSCO", "Eiger", "Titan" 636}; 637 638static char unofficial_names[][8] = {"100", "Ruffian"}; 639 640static char api_names[][16] = {"200", "Nautilus"}; 641 642static char eb164_names[][8] = {"EB164", "PC164", "LX164", "SX164", "RX164"}; 643static int eb164_indices[] = {0,0,0,1,1,1,1,1,2,2,2,2,3,3,3,3,4}; 644 645static char alcor_names[][16] = {"Alcor", "Maverick", "Bret"}; 646static int alcor_indices[] = {0,0,0,1,1,1,0,0,0,0,0,0,2,2,2,2,2,2}; 647 648static char eb64p_names[][16] = {"EB64+", "Cabriolet", "AlphaPCI64"}; 649static int eb64p_indices[] = {0,0,1,2}; 650 651static char eb66_names[][8] = {"EB66", "EB66+"}; 652static int eb66_indices[] = {0,0,1}; 653 654static char rawhide_names[][16] = { 655 "Dodge", "Wrangler", "Durango", "Tincup", "DaVinci" 656}; 657static int rawhide_indices[] = {0,0,0,1,1,2,2,3,3,4,4}; 658 659static char titan_names[][16] = { 660 "0", "Privateer" 661}; 662static int titan_indices[] = {0,1}; 663 664static char tsunami_names[][16] = { 665 "0", "DP264", "Warhol", "Windjammer", "Monet", "Clipper", 666 "Goldrush", "Webbrick", "Catamaran", "Brisbane", "Melbourne", 667 "Flying Clipper", "Shark" 668}; 669static int tsunami_indices[] = {0,1,2,3,4,5,6,7,8,9,10,11,12}; 670 671static struct alpha_machine_vector * __init 672get_sysvec(long type, long variation, long cpu) 673{ 674 static struct alpha_machine_vector *systype_vecs[] __initdata = 675 { 676 NULL, /* 0 */ 677 NULL, /* ADU */ 678 NULL, /* Cobra */ 679 NULL, /* Ruby */ 680 NULL, /* Flamingo */ 681 NULL, /* Mannequin */ 682 &jensen_mv, 683 NULL, /* Pelican */ 684 NULL, /* Morgan */ 685 NULL, /* Sable -- see below. */ 686 NULL, /* Medulla */ 687 &noname_mv, 688 NULL, /* Turbolaser */ 689 &avanti_mv, 690 NULL, /* Mustang */ 691 &alcor_mv, /* Alcor, Bret, Maverick. */ 692 NULL, /* Tradewind */ 693 NULL, /* Mikasa -- see below. */ 694 NULL, /* EB64 */ 695 NULL, /* EB66 -- see variation. */ 696 NULL, /* EB64+ -- see variation. */ 697 &alphabook1_mv, 698 &rawhide_mv, 699 NULL, /* K2 */ 700 NULL, /* Lynx */ 701 &xl_mv, 702 NULL, /* EB164 -- see variation. */ 703 NULL, /* Noritake -- see below. */ 704 NULL, /* Cortex */ 705 NULL, /* 29 */ 706 &miata_mv, 707 NULL, /* XXM */ 708 &takara_mv, 709 NULL, /* Yukon */ 710 NULL, /* Tsunami -- see variation. */ 711 &wildfire_mv, /* Wildfire */ 712 NULL, /* CUSCO */ 713 &eiger_mv, /* Eiger */ 714 NULL, /* Titan */ 715 }; 716 717 static struct alpha_machine_vector *unofficial_vecs[] __initdata = 718 { 719 NULL, /* 100 */ 720 &ruffian_mv, 721 }; 722 723 static struct alpha_machine_vector *api_vecs[] __initdata = 724 { 725 NULL, /* 200 */ 726 &nautilus_mv, 727 }; 728 729 static struct alpha_machine_vector *alcor_vecs[] __initdata = 730 { 731 &alcor_mv, &xlt_mv, &xlt_mv 732 }; 733 734 static struct alpha_machine_vector *eb164_vecs[] __initdata = 735 { 736 &eb164_mv, &pc164_mv, &lx164_mv, &sx164_mv, &rx164_mv 737 }; 738 739 static struct alpha_machine_vector *eb64p_vecs[] __initdata = 740 { 741 &eb64p_mv, 742 &cabriolet_mv, 743 &cabriolet_mv /* AlphaPCI64 */ 744 }; 745 746 static struct alpha_machine_vector *eb66_vecs[] __initdata = 747 { 748 &eb66_mv, 749 &eb66p_mv 750 }; 751 752 static struct alpha_machine_vector *titan_vecs[] __initdata = 753 { 754 NULL, 755 &privateer_mv, /* privateer */ 756 }; 757 758 static struct alpha_machine_vector *tsunami_vecs[] __initdata = 759 { 760 NULL, 761 &dp264_mv, /* dp264 */ 762 &dp264_mv, /* warhol */ 763 &dp264_mv, /* windjammer */ 764 &monet_mv, /* monet */ 765 &clipper_mv, /* clipper */ 766 &dp264_mv, /* goldrush */ 767 &webbrick_mv, /* webbrick */ 768 &dp264_mv, /* catamaran */ 769 NULL, /* brisbane? */ 770 NULL, /* melbourne? */ 771 NULL, /* flying clipper? */ 772 &shark_mv, /* shark */ 773 }; 774 775 /* ??? Do we need to distinguish between Rawhides? */ 776 777 struct alpha_machine_vector *vec; 778 779 /* Restore real CABRIO and EB66+ family names, ie EB64+ and EB66 */ 780 if (type < 0) 781 type = -type; 782 783 /* Search the system tables first... */ 784 vec = NULL; 785 if (type < N(systype_vecs)) { 786 vec = systype_vecs[type]; 787 } else if ((type > ST_API_BIAS) && 788 (type - ST_API_BIAS) < N(api_vecs)) { 789 vec = api_vecs[type - ST_API_BIAS]; 790 } else if ((type > ST_UNOFFICIAL_BIAS) && 791 (type - ST_UNOFFICIAL_BIAS) < N(unofficial_vecs)) { 792 vec = unofficial_vecs[type - ST_UNOFFICIAL_BIAS]; 793 } 794 795 /* If we've not found one, try for a variation. */ 796 797 if (!vec) { 798 /* Member ID is a bit-field. */ 799 long member = (variation >> 10) & 0x3f; 800 801 cpu &= 0xffffffff; /* make it usable */ 802 803 switch (type) { 804 case ST_DEC_ALCOR: 805 if (member < N(alcor_indices)) 806 vec = alcor_vecs[alcor_indices[member]]; 807 break; 808 case ST_DEC_EB164: 809 if (member < N(eb164_indices)) 810 vec = eb164_vecs[eb164_indices[member]]; 811 /* PC164 may show as EB164 variation with EV56 CPU, 812 but, since no true EB164 had anything but EV5... */ 813 if (vec == &eb164_mv && cpu == EV56_CPU) 814 vec = &pc164_mv; 815 break; 816 case ST_DEC_EB64P: 817 if (member < N(eb64p_indices)) 818 vec = eb64p_vecs[eb64p_indices[member]]; 819 break; 820 case ST_DEC_EB66: 821 if (member < N(eb66_indices)) 822 vec = eb66_vecs[eb66_indices[member]]; 823 break; 824 case ST_DEC_TITAN: 825 if (member < N(titan_indices)) 826 vec = titan_vecs[titan_indices[member]]; 827 break; 828 case ST_DEC_TSUNAMI: 829 if (member < N(tsunami_indices)) 830 vec = tsunami_vecs[tsunami_indices[member]]; 831 break; 832 case ST_DEC_1000: 833 if (cpu == EV5_CPU || cpu == EV56_CPU) 834 vec = &mikasa_primo_mv; 835 else 836 vec = &mikasa_mv; 837 break; 838 case ST_DEC_NORITAKE: 839 if (cpu == EV5_CPU || cpu == EV56_CPU) 840 vec = &noritake_primo_mv; 841 else 842 vec = &noritake_mv; 843 break; 844 case ST_DEC_2100_A500: 845 if (cpu == EV5_CPU || cpu == EV56_CPU) 846 vec = &sable_gamma_mv; 847 else 848 vec = &sable_mv; 849 break; 850 } 851 } 852 return vec; 853} 854 855static struct alpha_machine_vector * __init 856get_sysvec_byname(const char *name) 857{ 858 static struct alpha_machine_vector *all_vecs[] __initdata = 859 { 860 &alcor_mv, 861 &alphabook1_mv, 862 &avanti_mv, 863 &cabriolet_mv, 864 &clipper_mv, 865 &dp264_mv, 866 &eb164_mv, 867 &eb64p_mv, 868 &eb66_mv, 869 &eb66p_mv, 870 &eiger_mv, 871 &jensen_mv, 872 &lx164_mv, 873 &miata_mv, 874 &mikasa_mv, 875 &mikasa_primo_mv, 876 &monet_mv, 877 &nautilus_mv, 878 &noname_mv, 879 &noritake_mv, 880 &noritake_primo_mv, 881 &p2k_mv, 882 &pc164_mv, 883 &privateer_mv, 884 &rawhide_mv, 885 &ruffian_mv, 886 &rx164_mv, 887 &sable_mv, 888 &sable_gamma_mv, 889 &shark_mv, 890 &sx164_mv, 891 &takara_mv, 892 &webbrick_mv, 893 &wildfire_mv, 894 &xl_mv, 895 &xlt_mv 896 }; 897 898 int i, n = sizeof(all_vecs)/sizeof(*all_vecs); 899 for (i = 0; i < n; ++i) { 900 struct alpha_machine_vector *mv = all_vecs[i]; 901 if (strcasecmp(mv->vector_name, name) == 0) 902 return mv; 903 } 904 return NULL; 905} 906 907static void 908get_sysnames(long type, long variation, long cpu, 909 char **type_name, char **variation_name) 910{ 911 long member; 912 913 /* Restore real CABRIO and EB66+ family names, ie EB64+ and EB66 */ 914 if (type < 0) 915 type = -type; 916 917 /* If not in the tables, make it UNKNOWN, 918 else set type name to family */ 919 if (type < N(systype_names)) { 920 *type_name = systype_names[type]; 921 } else if ((type > ST_API_BIAS) && 922 (type - ST_API_BIAS) < N(api_names)) { 923 *type_name = api_names[type - ST_API_BIAS]; 924 } else if ((type > ST_UNOFFICIAL_BIAS) && 925 (type - ST_UNOFFICIAL_BIAS) < N(unofficial_names)) { 926 *type_name = unofficial_names[type - ST_UNOFFICIAL_BIAS]; 927 } else { 928 *type_name = sys_unknown; 929 *variation_name = sys_unknown; 930 return; 931 } 932 933 /* Set variation to "0"; if variation is zero, done */ 934 *variation_name = systype_names[0]; 935 if (variation == 0) { 936 return; 937 } 938 939 member = (variation >> 10) & 0x3f; /* member ID is a bit-field */ 940 941 cpu &= 0xffffffff; /* make it usable */ 942 943 switch (type) { /* select by family */ 944 default: /* default to variation "0" for now */ 945 break; 946 case ST_DEC_EB164: 947 if (member < N(eb164_indices)) 948 *variation_name = eb164_names[eb164_indices[member]]; 949 /* PC164 may show as EB164 variation, but with EV56 CPU, 950 so, since no true EB164 had anything but EV5... */ 951 if (eb164_indices[member] == 0 && cpu == EV56_CPU) 952 *variation_name = eb164_names[1]; /* make it PC164 */ 953 break; 954 case ST_DEC_ALCOR: 955 if (member < N(alcor_indices)) 956 *variation_name = alcor_names[alcor_indices[member]]; 957 break; 958 case ST_DEC_EB64P: 959 if (member < N(eb64p_indices)) 960 *variation_name = eb64p_names[eb64p_indices[member]]; 961 break; 962 case ST_DEC_EB66: 963 if (member < N(eb66_indices)) 964 *variation_name = eb66_names[eb66_indices[member]]; 965 break; 966 case ST_DEC_RAWHIDE: 967 if (member < N(rawhide_indices)) 968 *variation_name = rawhide_names[rawhide_indices[member]]; 969 break; 970 case ST_DEC_TITAN: 971 if (member < N(titan_indices)) 972 *variation_name = titan_names[titan_indices[member]]; 973 break; 974 case ST_DEC_TSUNAMI: 975 if (member < N(tsunami_indices)) 976 *variation_name = tsunami_names[tsunami_indices[member]]; 977 break; 978 } 979} 980 981/* 982 * A change was made to the HWRPB via an ECO and the following code 983 * tracks a part of the ECO. In HWRPB versions less than 5, the ECO 984 * was not implemented in the console firmware. If it's revision 5 or 985 * greater we can get the name of the platform as an ASCII string from 986 * the HWRPB. That's what this function does. It checks the revision 987 * level and if the string is in the HWRPB it returns the address of 988 * the string--a pointer to the name of the platform. 989 * 990 * Returns: 991 * - Pointer to a ASCII string if it's in the HWRPB 992 * - Pointer to a blank string if the data is not in the HWRPB. 993 */ 994 995static char * 996platform_string(void) 997{ 998 struct dsr_struct *dsr; 999 static char unk_system_string[] = "N/A"; 1000 1001 /* Go to the console for the string pointer. 1002 * If the rpb_vers is not 5 or greater the rpb 1003 * is old and does not have this data in it. 1004 */ 1005 if (hwrpb->revision < 5) 1006 return (unk_system_string); 1007 else { 1008 /* The Dynamic System Recognition struct 1009 * has the system platform name starting 1010 * after the character count of the string. 1011 */ 1012 dsr = ((struct dsr_struct *) 1013 ((char *)hwrpb + hwrpb->dsr_offset)); 1014 return ((char *)dsr + (dsr->sysname_off + 1015 sizeof(long))); 1016 } 1017} 1018 1019static int 1020get_nr_processors(struct percpu_struct *cpubase, unsigned long num) 1021{ 1022 struct percpu_struct *cpu; 1023 int i, count = 0; 1024 1025 for (i = 0; i < num; i++) { 1026 cpu = (struct percpu_struct *) 1027 ((char *)cpubase + i*hwrpb->processor_size); 1028 if ((cpu->flags & 0x1cc) == 0x1cc) 1029 count++; 1030 } 1031 return count; 1032} 1033 1034 1035static int 1036show_cpuinfo(struct seq_file *f, void *slot) 1037{ 1038 extern struct unaligned_stat { 1039 unsigned long count, va, pc; 1040 } unaligned[2]; 1041 1042 static char cpu_names[][8] = { 1043 "EV3", "EV4", "Simulate", "LCA4", "EV5", "EV45", "EV56", 1044 "EV6", "PCA56", "PCA57", "EV67", "EV68CB", "EV68AL", 1045 "EV68CX", "EV7", "EV79", "EV69" 1046 }; 1047 1048 struct percpu_struct *cpu = slot; 1049 unsigned int cpu_index; 1050 char *cpu_name; 1051 char *systype_name; 1052 char *sysvariation_name; 1053 int nr_processors; 1054 1055 cpu_index = (unsigned) (cpu->type - 1); 1056 cpu_name = "Unknown"; 1057 if (cpu_index < N(cpu_names)) 1058 cpu_name = cpu_names[cpu_index]; 1059 1060 get_sysnames(hwrpb->sys_type, hwrpb->sys_variation, 1061 cpu->type, &systype_name, &sysvariation_name); 1062 1063 nr_processors = get_nr_processors(cpu, hwrpb->nr_processors); 1064 1065 seq_printf(f, "cpu\t\t\t: Alpha\n" 1066 "cpu model\t\t: %s\n" 1067 "cpu variation\t\t: %ld\n" 1068 "cpu revision\t\t: %ld\n" 1069 "cpu serial number\t: %s\n" 1070 "system type\t\t: %s\n" 1071 "system variation\t: %s\n" 1072 "system revision\t\t: %ld\n" 1073 "system serial number\t: %s\n" 1074 "cycle frequency [Hz]\t: %lu %s\n" 1075 "timer frequency [Hz]\t: %lu.%02lu\n" 1076 "page size [bytes]\t: %ld\n" 1077 "phys. address bits\t: %ld\n" 1078 "max. addr. space #\t: %ld\n" 1079 "BogoMIPS\t\t: %lu.%02lu\n" 1080 "kernel unaligned acc\t: %ld (pc=%lx,va=%lx)\n" 1081 "user unaligned acc\t: %ld (pc=%lx,va=%lx)\n" 1082 "platform string\t\t: %s\n" 1083 "cpus detected\t\t: %d\n", 1084 cpu_name, cpu->variation, cpu->revision, 1085 (char*)cpu->serial_no, 1086 systype_name, sysvariation_name, hwrpb->sys_revision, 1087 (char*)hwrpb->ssn, 1088 est_cycle_freq ? : hwrpb->cycle_freq, 1089 est_cycle_freq ? "est." : "", 1090 hwrpb->intr_freq / 4096, 1091 (100 * hwrpb->intr_freq / 4096) % 100, 1092 hwrpb->pagesize, 1093 hwrpb->pa_bits, 1094 hwrpb->max_asn, 1095 loops_per_jiffy / (500000/HZ), 1096 (loops_per_jiffy / (5000/HZ)) % 100, 1097 unaligned[0].count, unaligned[0].pc, unaligned[0].va, 1098 unaligned[1].count, unaligned[1].pc, unaligned[1].va, 1099 platform_string(), nr_processors); 1100 1101#ifdef CONFIG_SMP 1102 seq_printf(f, "cpus active\t\t: %d\n" 1103 "cpu active mask\t\t: %016lx\n", 1104 smp_num_cpus, cpu_present_mask); 1105#endif 1106 1107 return 0; 1108} 1109 1110/* 1111 * We show only CPU #0 info. 1112 */ 1113static void * 1114c_start(struct seq_file *f, loff_t *pos) 1115{ 1116 return *pos ? NULL : (char *)hwrpb + hwrpb->processor_offset; 1117} 1118 1119static void * 1120c_next(struct seq_file *f, void *v, loff_t *pos) 1121{ 1122 return NULL; 1123} 1124 1125static void 1126c_stop(struct seq_file *f, void *v) 1127{ 1128} 1129 1130struct seq_operations cpuinfo_op = { 1131 start: c_start, 1132 next: c_next, 1133 stop: c_stop, 1134 show: show_cpuinfo, 1135}; 1136 1137 1138static int alpha_panic_event(struct notifier_block *this, 1139 unsigned long event, 1140 void *ptr) 1141{ 1142 /* If we are using SRM and serial console, just hard halt here. */ 1143 if (alpha_using_srm && srmcons_output) 1144 __halt(); 1145 return NOTIFY_DONE; 1146} 1147