diff options
Diffstat (limited to 'arch/sparc/kernel')
-rw-r--r-- | arch/sparc/kernel/process.c | 8 | ||||
-rw-r--r-- | arch/sparc/kernel/prom.c | 131 | ||||
-rw-r--r-- | arch/sparc/kernel/setup.c | 65 |
3 files changed, 137 insertions, 67 deletions
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 8c37f8f5adb7..33f7a3ddb104 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -39,6 +39,7 @@ #include <asm/processor.h> #include <asm/psr.h> #include <asm/elf.h> +#include <asm/prom.h> #include <asm/unistd.h> /* @@ -150,7 +151,7 @@ void machine_halt(void) local_irq_enable(); mdelay(8); local_irq_disable(); - if (!serial_console && prom_palette) + if (prom_palette) prom_palette (1); prom_halt(); panic("Halt failed!"); @@ -166,7 +167,7 @@ void machine_restart(char * cmd) p = strchr (reboot_command, '\n'); if (p) *p = 0; - if (!serial_console && prom_palette) + if (prom_palette) prom_palette (1); if (cmd) prom_reboot(cmd); @@ -179,7 +180,8 @@ void machine_restart(char * cmd) void machine_power_off(void) { #ifdef CONFIG_SUN_AUXIO - if (auxio_power_register && (!serial_console || scons_pwroff)) + if (auxio_power_register && + (strcmp(of_console_device->type, "serial") || scons_pwroff)) *auxio_power_register |= AUXIO_POWER_OFF; #endif machine_halt(); diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c index 012f98346bcd..e3a537650db1 100644 --- a/arch/sparc/kernel/prom.c +++ b/arch/sparc/kernel/prom.c @@ -397,6 +397,135 @@ static struct device_node * __init build_tree(struct device_node *parent, phandl return dp; } +struct device_node *of_console_device; +EXPORT_SYMBOL(of_console_device); + +char *of_console_path; +EXPORT_SYMBOL(of_console_path); + +char *of_console_options; +EXPORT_SYMBOL(of_console_options); + +extern void restore_current(void); + +static void __init of_console_init(void) +{ + char *msg = "OF stdout device is: %s\n"; + struct device_node *dp; + unsigned long flags; + const char *type; + phandle node; + int skip, fd; + + of_console_path = prom_early_alloc(256); + + switch (prom_vers) { + case PROM_V0: + case PROM_SUN4: + skip = 0; + switch (*romvec->pv_stdout) { + case PROMDEV_SCREEN: + type = "display"; + break; + + case PROMDEV_TTYB: + skip = 1; + /* FALLTHRU */ + + case PROMDEV_TTYA: + type = "serial"; + break; + + default: + prom_printf("Invalid PROM_V0 stdout value %u\n", + *romvec->pv_stdout); + prom_halt(); + } + + for_each_node_by_type(dp, type) { + if (!skip--) + break; + } + if (!dp) { + prom_printf("Cannot find PROM_V0 console node.\n"); + prom_halt(); + } + of_console_device = dp; + + strcpy(of_console_path, dp->full_name); + if (!strcmp(type, "serial")) { + strcat(of_console_path, + (skip ? ":b" : ":a")); + } + break; + + default: + case PROM_V2: + case PROM_V3: + fd = *romvec->pv_v2bootargs.fd_stdout; + + spin_lock_irqsave(&prom_lock, flags); + node = (*romvec->pv_v2devops.v2_inst2pkg)(fd); + restore_current(); + spin_unlock_irqrestore(&prom_lock, flags); + + if (!node) { + prom_printf("Cannot resolve stdout node from " + "instance %08x.\n", fd); + prom_halt(); + } + dp = of_find_node_by_phandle(node); + type = of_get_property(dp, "device_type", NULL); + + if (!type) { + prom_printf("Console stdout lacks " + "device_type property.\n"); + prom_halt(); + } + + if (strcmp(type, "display") && strcmp(type, "serial")) { + prom_printf("Console device_type is neither display " + "nor serial.\n"); + prom_halt(); + } + + of_console_device = dp; + + if (prom_vers == PROM_V2) { + strcpy(of_console_path, dp->full_name); + switch (*romvec->pv_stdout) { + case PROMDEV_TTYA: + strcat(of_console_path, ":a"); + break; + case PROMDEV_TTYB: + strcat(of_console_path, ":b"); + break; + } + } else { + const char *path; + + dp = of_find_node_by_path("/"); + path = of_get_property(dp, "stdout-path", NULL); + if (!path) { + prom_printf("No stdout-path in root node.\n"); + prom_halt(); + } + strcpy(of_console_path, path); + } + break; + } + + of_console_options = strrchr(of_console_path, ':'); + if (of_console_options) { + of_console_options++; + if (*of_console_options == '\0') + of_console_options = NULL; + } + + prom_printf(msg, of_console_path); + printk(msg, of_console_path); +} + void __init prom_build_devicetree(void) { struct device_node **nextp; @@ -409,6 +538,8 @@ void __init prom_build_devicetree(void) allnodes->child = build_tree(allnodes, prom_getchild(allnodes->node), &nextp); + of_console_init(); + printk("PROM: Built device tree with %u bytes of memory.\n", prom_early_allocated); } diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index 64c0ed98820a..f8228383895a 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -146,31 +146,6 @@ static void __init process_switch(char c) } } -static void __init process_console(char *commands) -{ - serial_console = 0; - commands += 8; - /* Linux-style serial */ - if (!strncmp(commands, "ttyS", 4)) - serial_console = simple_strtoul(commands + 4, NULL, 10) + 1; - else if (!strncmp(commands, "tty", 3)) { - char c = *(commands + 3); - /* Solaris-style serial */ - if (c == 'a' || c == 'b') - serial_console = c - 'a' + 1; - /* else Linux-style fbcon, not serial */ - } -#if defined(CONFIG_PROM_CONSOLE) - if (!strncmp(commands, "prom", 4)) { - char *p; - - for (p = commands - 8; *p && *p != ' '; p++) - *p = ' '; - conswitchp = &prom_con; - } -#endif -} - static void __init boot_flags_init(char *commands) { while (*commands) { @@ -187,9 +162,7 @@ static void __init boot_flags_init(char *commands) process_switch(*commands++); continue; } - if (!strncmp(commands, "console=", 8)) { - process_console(commands); - } else if (!strncmp(commands, "mem=", 4)) { + if (!strncmp(commands, "mem=", 4)) { /* * "mem=XXX[kKmM] overrides the PROM-reported * memory size. @@ -341,41 +314,6 @@ void __init setup_arch(char **cmdline_p) smp_setup_cpu_possible_map(); } -static int __init set_preferred_console(void) -{ - int idev, odev; - - /* The user has requested a console so this is already set up. */ - if (serial_console >= 0) - return -EBUSY; - - idev = prom_query_input_device(); - odev = prom_query_output_device(); - if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) { - serial_console = 0; - } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) { - serial_console = 1; - } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) { - serial_console = 2; - } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OTTYA) { - prom_printf("MrCoffee ttya\n"); - serial_console = 1; - } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OSCREEN) { - serial_console = 0; - prom_printf("MrCoffee keyboard\n"); - } else { - prom_printf("Confusing console (idev %d, odev %d)\n", - idev, odev); - serial_console = 1; - } - - if (serial_console) - return add_preferred_console("ttyS", serial_console - 1, NULL); - - return -ENODEV; -} -console_initcall(set_preferred_console); - extern char *sparc_cpu_type; extern char *sparc_fpu_type; @@ -461,7 +399,6 @@ void sun_do_break(void) prom_cmdline(); } -int serial_console = -1; int stop_a_enabled = 1; static int __init topology_init(void) |