patch-2.4.0-test2 linux/arch/alpha/kernel/setup.c
Next file: linux/arch/alpha/kernel/signal.c
Previous file: linux/arch/alpha/kernel/ptrace.c
Back to the patch index
Back to the overall index
- Lines: 423
- Date:
Mon Jun 19 17:59:32 2000
- Orig file:
v2.4.0-test1/linux/arch/alpha/kernel/setup.c
- Orig date:
Wed Apr 26 16:34:06 2000
diff -u --recursive --new-file v2.4.0-test1/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c
@@ -34,6 +34,15 @@
#include <linux/blk.h>
#endif
+#include <linux/notifier.h>
+extern struct notifier_block *panic_notifier_list;
+static int alpha_panic_event(struct notifier_block *, unsigned long, void *);
+static struct notifier_block alpha_panic_block = {
+ alpha_panic_event,
+ NULL,
+ INT_MAX /* try to do it first */
+};
+
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/system.h>
@@ -42,6 +51,7 @@
#include <asm/io.h>
#include <asm/pci.h>
#include <asm/mmu_context.h>
+#include <asm/console.h>
#include "proto.h"
#include "pci_impl.h"
@@ -53,6 +63,17 @@
/* Which processor we booted from. */
int boot_cpuid;
+/* Using SRM callbacks for initial console output. This works from
+ setup_arch() time through the end of init_IRQ(), as those places
+ are under our control.
+
+ By default, OFF; set it with a bootcommand arg of "srmcons".
+*/
+int srmcons_output = 0;
+
+/* Enforce a memory size limit; useful for testing. By default, none. */
+unsigned long mem_size_limit = 0;
+
#ifdef CONFIG_ALPHA_GENERIC
struct alpha_machine_vector alpha_mv;
int alpha_using_srm;
@@ -139,6 +160,7 @@
WEAK(noritake_primo_mv);
WEAK(p2k_mv);
WEAK(pc164_mv);
+WEAK(privateer_mv);
WEAK(rawhide_mv);
WEAK(ruffian_mv);
WEAK(rx164_mv);
@@ -147,6 +169,7 @@
WEAK(sx164_mv);
WEAK(takara_mv);
WEAK(webbrick_mv);
+WEAK(wildfire_mv);
WEAK(xl_mv);
WEAK(xlt_mv);
@@ -202,14 +225,33 @@
for ((cluster) = (memdesc)->cluster, (i) = 0; \
(i) < (memdesc)->numclusters; (i)++, (cluster)++)
+static unsigned long __init
+get_mem_size_limit(char *s)
+{
+ unsigned long end = 0;
+ char *from = s;
+
+ end = simple_strtoul(from, &from, 0);
+ if ( *from == 'K' || *from == 'k' ) {
+ end = end << 10;
+ from++;
+ } else if ( *from == 'M' || *from == 'm' ) {
+ end = end << 20;
+ from++;
+ } else if ( *from == 'G' || *from == 'g' ) {
+ end = end << 30;
+ from++;
+ }
+ return end >> PAGE_SHIFT; /* Return the PFN of the limit. */
+}
+
static void __init
-setup_memory(void)
+setup_memory(void * kernel_end)
{
struct memclust_struct * cluster;
struct memdesc_struct * memdesc;
unsigned long start_pfn, bootmap_size, bootmap_pages, bootmap_start;
unsigned long start, end;
- extern char _end[];
int i;
/* Find free clusters, and init and free the bootmem accordingly. */
@@ -232,15 +274,23 @@
max_low_pfn = end;
}
- /* Find the end of the kernel memory. */
- start_pfn = PFN_UP(virt_to_phys(_end));
+ if (mem_size_limit && max_low_pfn >= mem_size_limit)
+ {
+ printk("setup: forcing memory size to %ldK (from %ldK).\n",
+ mem_size_limit << (PAGE_SHIFT - 10),
+ max_low_pfn << (PAGE_SHIFT - 10));
+ max_low_pfn = mem_size_limit;
+ }
+
+ /* Find the end of the memory used by the kernel. */
+ start_pfn = PFN_UP(virt_to_phys(kernel_end));
bootmap_start = -1;
try_again:
if (max_low_pfn <= start_pfn)
panic("not enough memory to boot");
- /* We need to know how many physically contigous pages
+ /* We need to know how many physically contiguous pages
we'll need for the bootmap. */
bootmap_pages = bootmem_bootmap_pages(max_low_pfn);
@@ -307,14 +357,14 @@
printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
(void *) initrd_start, INITRD_SIZE);
- if (initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) {
+ if ((void *)initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) {
printk("initrd extends beyond end of memory "
- "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+ "(0x%08lx > 0x%p)\ndisabling initrd\n",
initrd_end,
phys_to_virt(PFN_PHYS(max_low_pfn)));
initrd_start = initrd_end = 0;
} else {
- reserve_bootmem(virt_to_phys(initrd_start),
+ reserve_bootmem(virt_to_phys((void *)initrd_start),
INITRD_SIZE);
}
}
@@ -346,20 +396,98 @@
#undef PFN_PHYS
#undef PFN_MAX
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
+/*
+ * Manage the SRM callbacks as a "console".
+ */
+static struct console srmcons;
+
+void __init register_srm_console(void)
+{
+ register_console(&srmcons);
+}
+
+void __init unregister_srm_console(void)
+{
+ unregister_console(&srmcons);
+}
+
+static void srm_console_write(struct console *co, const char *s,
+ unsigned count)
+{
+ srm_printk(s);
+}
+
+static kdev_t srm_console_device(struct console *c)
+{
+ /* Huh? */
+ return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+static int srm_console_wait_key(struct console *co)
+{
+ /* Huh? */
+ return 1;
+}
+
+static int __init srm_console_setup(struct console *co, char *options)
+{
+ return 1;
+}
+
+static struct console srmcons = {
+ "srm0",
+ srm_console_write,
+ NULL,
+ srm_console_device,
+ srm_console_wait_key,
+ NULL,
+ srm_console_setup,
+ CON_PRINTBUFFER | CON_ENABLED, /* fake it out */
+ -1,
+ 0,
+ NULL
+};
+
+#else
+void __init register_srm_console(void)
+{
+}
+void __init unregister_srm_console(void)
+{
+}
+#endif
+
void __init
setup_arch(char **cmdline_p)
{
struct alpha_machine_vector *vec = NULL;
struct percpu_struct *cpu;
char *type_name, *var_name, *p;
+ extern char _end;
+ void * kernel_end = &_end; /* end of kernel */
hwrpb = (struct hwrpb_struct*) __va(INIT_HWRPB->phys_addr);
boot_cpuid = hard_smp_processor_id();
+ /* Register a call for panic conditions. */
+ notifier_chain_register(&panic_notifier_list, &alpha_panic_block);
+
+#ifdef CONFIG_ALPHA_GENERIC
+ /* Assume that we've booted from SRM if we havn't booted from MILO.
+ Detect the later by looking for "MILO" in the system serial nr. */
+ alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0;
+#endif
+
+ /* If we are using SRM, we want to allow callbacks
+ as early as possible, so do this NOW, and then
+ they should work immediately thereafter.
+ */
+ kernel_end = callback_init(kernel_end);
+
/*
* Locate the command line.
*/
-
/* Hack for Jensen... since we're restricted to 8 or 16 chars for
boot flags depending on the boot mode, we need some shorthand.
This should do for installation. */
@@ -375,7 +503,6 @@
/*
* Process command-line arguments.
*/
-
for (p = strtok(command_line, " \t"); p ; p = strtok(NULL, " \t")) {
if (strncmp(p, "alpha_mv=", 9) == 0) {
vec = get_sysvec_byname(p+9);
@@ -385,15 +512,27 @@
est_cycle_freq = simple_strtol(p+6, NULL, 0);
continue;
}
+ if (strncmp(p, "mem=", 4) == 0) {
+ mem_size_limit = get_mem_size_limit(p+4);
+ continue;
+ }
+ if (strncmp(p, "srmcons", 7) == 0) {
+ srmcons_output = 1;
+ continue;
+ }
}
- /* Replace the command line, not that we've killed it with strtok. */
+ /* Replace the command line, now that we've killed it with strtok. */
strcpy(command_line, saved_command_line);
+ /* If we want SRM console printk echoing early, do it now. */
+ if (alpha_using_srm && srmcons_output) {
+ register_srm_console();
+ }
+
/*
* Indentify and reconfigure for the current system.
*/
-
get_sysnames(hwrpb->sys_type, hwrpb->sys_variation,
&type_name, &var_name);
if (*var_name == '0')
@@ -415,12 +554,6 @@
alpha_mv = *vec;
}
-#ifdef CONFIG_ALPHA_GENERIC
- /* Assume that we've booted from SRM if we havn't booted from MILO.
- Detect the later by looking for "MILO" in the system serial nr. */
- alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0;
-#endif
-
printk("Booting "
#ifdef CONFIG_ALPHA_GENERIC
"GENERIC "
@@ -433,10 +566,9 @@
printk("Command line: %s\n", command_line);
/*
- * Sync with the HAE
+ * Sync up the HAE.
+ * Save the SRM's current value for restoration.
*/
-
- /* Save the SRM's current value for restoration. */
srm_hae = *alpha_mv.hae_register;
__set_hae(alpha_mv.hae_cache);
@@ -444,7 +576,7 @@
wrmces(0x7);
/* Find our memory. */
- setup_memory();
+ setup_memory(kernel_end);
/* Initialize the machine. Usually has to do with setting up
DMA windows and the like. */
@@ -499,7 +631,7 @@
"Mikasa", "EB64", "EB66", "EB64+", "AlphaBook1",
"Rawhide", "K2", "Lynx", "XL", "EB164", "Noritake",
"Cortex", "29", "Miata", "XXM", "Takara", "Yukon",
- "Tsunami", "Wildfire", "CUSCO", "Eiger"
+ "Tsunami", "Wildfire", "CUSCO", "Eiger", "Titan"
};
static char unofficial_names[][8] = {"100", "Ruffian"};
@@ -523,6 +655,11 @@
};
static int rawhide_indices[] = {0,0,0,1,1,2,2,3,3,4,4};
+static char titan_names[][16] = {
+ "0", "Privateer"
+};
+static int titan_indices[] = {0,1};
+
static char tsunami_names[][16] = {
"0", "DP264", "Warhol", "Windjammer", "Monet", "Clipper",
"Goldrush", "Webbrick", "Catamaran"
@@ -569,9 +706,10 @@
&takara_mv,
NULL, /* Yukon */
NULL, /* Tsunami -- see variation. */
- NULL, /* Wildfire */
+ &wildfire_mv, /* Wildfire */
NULL, /* CUSCO */
&eiger_mv, /* Eiger */
+ NULL, /* Titan */
};
static struct alpha_machine_vector *unofficial_vecs[] __initlocaldata =
@@ -609,6 +747,12 @@
&eb66p_mv
};
+ static struct alpha_machine_vector *titan_vecs[] __initlocaldata =
+ {
+ NULL,
+ &privateer_mv, /* privateer */
+ };
+
static struct alpha_machine_vector *tsunami_vecs[] __initlocaldata =
{
NULL,
@@ -665,6 +809,10 @@
if (member < N(eb66_indices))
vec = eb66_vecs[eb66_indices[member]];
break;
+ case ST_DEC_TITAN:
+ if (member < N(titan_indices))
+ vec = titan_vecs[titan_indices[member]];
+ break;
case ST_DEC_TSUNAMI:
if (member < N(tsunami_indices))
vec = tsunami_vecs[tsunami_indices[member]];
@@ -723,6 +871,7 @@
&noritake_primo_mv,
&p2k_mv,
&pc164_mv,
+ &privateer_mv,
&rawhide_mv,
&ruffian_mv,
&rx164_mv,
@@ -731,6 +880,7 @@
&sx164_mv,
&takara_mv,
&webbrick_mv,
+ &wildfire_mv,
&xl_mv,
&xlt_mv
};
@@ -801,6 +951,10 @@
if (member < N(rawhide_indices))
*variation_name = rawhide_names[rawhide_indices[member]];
break;
+ case ST_DEC_TITAN:
+ if (member < N(titan_indices))
+ *variation_name = titan_names[titan_indices[member]];
+ break;
case ST_DEC_TSUNAMI:
if (member < N(tsunami_indices))
*variation_name = tsunami_names[tsunami_indices[member]];
@@ -873,7 +1027,7 @@
static char cpu_names[][8] = {
"EV3", "EV4", "Simulate", "LCA4", "EV5", "EV45", "EV56",
- "EV6", "PCA56", "PCA57", "EV67"
+ "EV6", "PCA56", "PCA57", "EV67", "EV68CB", "EV68AL"
};
struct percpu_struct *cpu;
@@ -935,4 +1089,17 @@
#endif
return len;
+}
+
+static int alpha_panic_event(struct notifier_block *this,
+ unsigned long event,
+ void *ptr)
+{
+#if 1
+ /* FIXME FIXME FIXME */
+ /* If we are using SRM and serial console, just hard halt here. */
+ if (alpha_using_srm && srmcons_output)
+ __halt();
+#endif
+ return NOTIFY_DONE;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)