File: /usr/src/linux/arch/alpha/kernel/setup.c

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