[SPARC]: Fix serial console device detection.
authorDavid S. Miller <davem@sunset.davemloft.net>
Fri, 20 Jul 2007 23:59:26 +0000 (16:59 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Fri, 20 Jul 2007 23:59:26 +0000 (16:59 -0700)
The current scheme works on static interpretation of text names, which
is wrong.

The output-device setting, for example, must be resolved via an alias
or similar to a full path name to the console device.

Paths also contain an optional set of 'options', which starts with a
colon at the end of the path.  The option area is used to specify
which of two serial ports ('a' or 'b') the path refers to when a
device node drives multiple ports.  'a' is assumed if the option
specification is missing.

This was caught by the UltraSPARC-T1 simulator.  The 'output-device'
property was set to 'ttya' and we didn't pick upon the fact that this
is an OBP alias set to '/virtual-devices/console'.  Instead we saw it
as the first serial console device, instead of the hypervisor console.

The infrastructure is now there to take advantage of this to resolve
the console correctly even in multi-head situations in fbcon too.

Thanks to Greg Onufer for the bug report.

Signed-off-by: David S. Miller <davem@davemloft.net>
26 files changed:
arch/sparc/kernel/process.c
arch/sparc/kernel/prom.c
arch/sparc/kernel/setup.c
arch/sparc/prom/console.c
arch/sparc/prom/misc.c
arch/sparc64/kernel/power.c
arch/sparc64/kernel/process.c
arch/sparc64/kernel/prom.c
arch/sparc64/kernel/setup.c
arch/sparc64/kernel/sparc64_ksyms.c
arch/sparc64/prom/console.c
arch/sparc64/prom/misc.c
arch/sparc64/prom/tree.c
drivers/serial/suncore.c
drivers/serial/suncore.h
drivers/serial/sunhv.c
drivers/serial/sunsab.c
drivers/serial/sunsu.c
drivers/serial/sunzilog.c
drivers/video/aty/atyfb_base.c
drivers/video/igafb.c
include/asm-sparc/oplib.h
include/asm-sparc/prom.h
include/asm-sparc64/oplib.h
include/asm-sparc64/prom.h
include/asm-sparc64/system.h

index 8c37f8f5adb7f0ef2d49f5910c984f22307b2951..33f7a3ddb1046b374a4804dad958e1c6d429b74c 100644 (file)
@@ -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();
index 012f98346bcd54405daef3e8a01f95a733665bde..e3a537650db1e8792c0d7a7978b0e52ab3e7fe2e 100644 (file)
@@ -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);
 }
index 64c0ed98820aa8870f7107e09c09c8df69fddd50..f8228383895ac9f38c51709c9af3c76ac13d2ba1 100644 (file)
@@ -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)
index 4e6e41d3291d11d75b624c9d7b8f5f2021bae90a..8d1cfb0d5068544205cdda1e516cb65636ed31bc 100644 (file)
@@ -102,119 +102,3 @@ prom_putchar(char c)
        while(prom_nbputchar(c) == -1) ;
        return;
 }
-
-/* Query for input device type */
-enum prom_input_device
-prom_query_input_device(void)
-{
-       unsigned long flags;
-       int st_p;
-       char propb[64];
-       char *p;
-       int propl;
-
-       switch(prom_vers) {
-       case PROM_V0:
-       case PROM_V2:
-       case PROM_SUN4:
-       default:
-               switch(*romvec->pv_stdin) {
-               case PROMDEV_KBD:       return PROMDEV_IKBD;
-               case PROMDEV_TTYA:      return PROMDEV_ITTYA;
-               case PROMDEV_TTYB:      return PROMDEV_ITTYB;
-               default:
-                       return PROMDEV_I_UNK;
-               };
-       case PROM_V3:
-               spin_lock_irqsave(&prom_lock, flags);
-               st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdin);
-               restore_current();
-               spin_unlock_irqrestore(&prom_lock, flags);
-               if(prom_node_has_property(st_p, "keyboard"))
-                       return PROMDEV_IKBD;
-               if (prom_getproperty(st_p, "name", propb, sizeof(propb)) != -1) {
-                       if(strncmp(propb, "keyboard", sizeof("serial")) == 0)
-                               return PROMDEV_IKBD;
-               }
-               if (prom_getproperty(st_p, "device_type", propb, sizeof(propb)) != -1) {
-               if(strncmp(propb, "serial", sizeof("serial")))
-                       return PROMDEV_I_UNK;
-               }
-               propl = prom_getproperty(prom_root_node, "stdin-path", propb, sizeof(propb));
-               if(propl > 2) {
-                       p = propb;
-                       while(*p) p++; p -= 2;
-                       if(p[0] == ':') {
-                               if(p[1] == 'a')
-                                       return PROMDEV_ITTYA;
-                               else if(p[1] == 'b')
-                                       return PROMDEV_ITTYB;
-                       }
-               }
-               return PROMDEV_I_UNK;
-       }
-}
-
-/* Query for output device type */
-
-enum prom_output_device
-prom_query_output_device(void)
-{
-       unsigned long flags;
-       int st_p;
-       char propb[64];
-       char *p;
-       int propl;
-
-       switch(prom_vers) {
-       case PROM_V0:
-       case PROM_SUN4:
-               switch(*romvec->pv_stdin) {
-               case PROMDEV_SCREEN:    return PROMDEV_OSCREEN;
-               case PROMDEV_TTYA:      return PROMDEV_OTTYA;
-               case PROMDEV_TTYB:      return PROMDEV_OTTYB;
-               };
-               break;
-       case PROM_V2:
-       case PROM_V3:
-               spin_lock_irqsave(&prom_lock, flags);
-               st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdout);
-               restore_current();
-               spin_unlock_irqrestore(&prom_lock, flags);
-               propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb));
-               if (propl == sizeof("display") &&
-                       strncmp("display", propb, sizeof("display")) == 0)
-               {
-                       return PROMDEV_OSCREEN;
-               }
-               if(prom_vers == PROM_V3) {
-                       if(propl >= 0 &&
-                           strncmp("serial", propb, sizeof("serial")) != 0)
-                               return PROMDEV_O_UNK;
-                       propl = prom_getproperty(prom_root_node, "stdout-path",
-                                                propb, sizeof(propb));
-                       if(propl == CON_SIZE_JMC &&
-                           strncmp(propb, con_name_jmc, CON_SIZE_JMC) == 0)
-                               return PROMDEV_OTTYA;
-                       if(propl > 2) {
-                               p = propb;
-                               while(*p) p++; p-= 2;
-                               if(p[0]==':') {
-                                       if(p[1] == 'a')
-                                               return PROMDEV_OTTYA;
-                                       else if(p[1] == 'b')
-                                               return PROMDEV_OTTYB;
-                               }
-                       }
-               } else {
-                       switch(*romvec->pv_stdin) {
-                       case PROMDEV_TTYA:      return PROMDEV_OTTYA;
-                       case PROMDEV_TTYB:      return PROMDEV_OTTYB;
-                       };
-               }
-               break;
-       default:
-               ;
-       };
-       return PROMDEV_O_UNK;
-}
index 1942c7c05cb18d350005ea19bcf043136a9f5755..37cff5f54704aaf205f66689582acb744ca55110 100644 (file)
@@ -58,7 +58,7 @@ prom_cmdline(void)
        extern void install_linux_ticker(void);
        unsigned long flags;
 
-       if(!serial_console && prom_palette)
+       if (prom_palette)
                prom_palette (1);
        spin_lock_irqsave(&prom_lock, flags);
        install_obp_ticker();
@@ -69,7 +69,7 @@ prom_cmdline(void)
 #ifdef CONFIG_SUN_AUXIO
        set_auxio(AUXIO_LED, 0);
 #endif
-       if(!serial_console && prom_palette)
+       if (prom_palette)
                prom_palette (0);
 }
 
index b00feb01c16ffac14edc01483ded150aaf8a52f6..881a09ee4c4c15ae4a2fac487184fad0a6c8fd06 100644 (file)
@@ -46,7 +46,7 @@ static void (*poweroff_method)(void) = machine_alt_power_off;
 void machine_power_off(void)
 {
        sstate_poweroff();
-       if (!serial_console || scons_pwroff) {
+       if (strcmp(of_console_device->type, "serial") || scons_pwroff) {
                if (power_reg) {
                        /* Both register bits seem to have the
                         * same effect, so until I figure out
index 93557507ec9f76d765783677b800152ef00de20a..fd7899ba1d70bde8edee7211139081fe7bad88f9 100644 (file)
@@ -119,7 +119,7 @@ extern void (*prom_keyboard)(void);
 void machine_halt(void)
 {
        sstate_halt();
-       if (!serial_console && prom_palette)
+       if (prom_palette)
                prom_palette (1);
        if (prom_keyboard)
                prom_keyboard();
@@ -130,7 +130,7 @@ void machine_halt(void)
 void machine_alt_power_off(void)
 {
        sstate_poweroff();
-       if (!serial_console && prom_palette)
+       if (prom_palette)
                prom_palette(1);
        if (prom_keyboard)
                prom_keyboard();
@@ -145,7 +145,7 @@ void machine_restart(char * cmd)
        sstate_reboot();
        p = strchr (reboot_command, '\n');
        if (p) *p = 0;
-       if (!serial_console && prom_palette)
+       if (prom_palette)
                prom_palette (1);
        if (prom_keyboard)
                prom_keyboard();
index 2b2017ce2267b8e973f160e2b5c16bcf6002ecd2..f4e0a9ad9be30b000895d5246d7f5318b1b11453 100644 (file)
@@ -1646,6 +1646,60 @@ static void __init of_fill_in_cpu_data(void)
        smp_fill_in_sib_core_maps();
 }
 
+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);
+
+static void __init of_console_init(void)
+{
+       char *msg = "OF stdout device is: %s\n";
+       struct device_node *dp;
+       const char *type;
+       phandle node;
+
+       of_console_path = prom_early_alloc(256);
+       if (prom_ihandle2path(prom_stdout, of_console_path, 256) < 0) {
+               prom_printf("Cannot obtain path of stdout.\n");
+               prom_halt();
+       }
+       of_console_options = strrchr(of_console_path, ':');
+       if (of_console_options) {
+               of_console_options++;
+               if (*of_console_options == '\0')
+                       of_console_options = NULL;
+       }
+
+       node = prom_inst2pkg(prom_stdout);
+       if (!node) {
+               prom_printf("Cannot resolve stdout node from "
+                           "instance %08x.\n", prom_stdout);
+               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;
+
+       prom_printf(msg, of_console_path);
+       printk(msg, of_console_path);
+}
+
 void __init prom_build_devicetree(void)
 {
        struct device_node **nextp;
@@ -1658,6 +1712,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);
 
index aafde3dd9fd4996af17f88f4d486aec214cdfe63..0f5be828ee92614c8465055552a192e042274d47 100644 (file)
@@ -133,33 +133,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;
-                       prom_printf ("Using /dev/tty%c as console.\n", c);
-               }
-               /* 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) {
@@ -176,9 +149,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.
@@ -378,44 +349,6 @@ void __init setup_arch(char **cmdline_p)
        paging_init();
 }
 
-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_IRSC && odev == PROMDEV_ORSC) {
-               serial_console = 3;
-       } else if (idev == PROMDEV_IVCONS && odev == PROMDEV_OVCONS) {
-               /* sunhv_console_init() doesn't check the serial_console
-                * value anyways...
-                */
-               serial_console = 4;
-               return add_preferred_console("ttyHV", 0, NULL);
-       } else {
-               prom_printf("Inconsistent console: "
-                           "input %d, output %d\n",
-                           idev, odev);
-               prom_halt();
-       }
-
-       if (serial_console)
-               return add_preferred_console("ttyS", serial_console - 1, NULL);
-
-       return -ENODEV;
-}
-console_initcall(set_preferred_console);
-
 /* BUFFER is PAGE_SIZE bytes long. */
 
 extern char *sparc_cpu_type;
@@ -508,5 +441,4 @@ void sun_do_break(void)
        prom_cmdline();
 }
 
-int serial_console = -1;
 int stop_a_enabled = 1;
index 719d676c2ddc5c2875a675f4bf3fe9bacc300b6d..7d36531aa5b98d3e243a1917ceb595a5f870cf7a 100644 (file)
@@ -330,7 +330,6 @@ EXPORT_SYMBOL(VISenter);
 
 /* for input/keybdev */
 EXPORT_SYMBOL(sun_do_break);
-EXPORT_SYMBOL(serial_console);
 EXPORT_SYMBOL(stop_a_enabled);
 
 #ifdef CONFIG_DEBUG_BUGVERBOSE
index 7c25c54cefdc77e04ef4ea2470bff043195654fa..3fafa9a8b50bb3d541ebbc0a9814379b292dcbd2 100644 (file)
@@ -73,88 +73,3 @@ prom_puts(const char *s, int len)
                           P1275_INOUT(3,1),
                           prom_stdout, s, P1275_SIZE(len));
 }
-
-/* Query for input device type */
-enum prom_input_device
-prom_query_input_device(void)
-{
-       int st_p;
-       char propb[64];
-
-       st_p = prom_inst2pkg(prom_stdin);
-       if(prom_node_has_property(st_p, "keyboard"))
-               return PROMDEV_IKBD;
-       prom_getproperty(st_p, "device_type", propb, sizeof(propb));
-       if(strncmp(propb, "serial", 6))
-               return PROMDEV_I_UNK;
-       /* FIXME: Is there any better way how to find out? */   
-       memset(propb, 0, sizeof(propb));
-       st_p = prom_finddevice ("/options");
-       prom_getproperty(st_p, "input-device", propb, sizeof(propb));
-
-       /*
-        * If we get here with propb == 'keyboard', we are on ttya, as
-        * the PROM defaulted to this due to 'no input device'.
-        */
-       if (!strncmp(propb, "keyboard", 8))
-               return PROMDEV_ITTYA;
-
-       if (!strncmp (propb, "rsc", 3))
-               return PROMDEV_IRSC;
-
-       if (!strncmp (propb, "virtual-console", 3))
-               return PROMDEV_IVCONS;
-
-       if (strncmp (propb, "tty", 3) || !propb[3])
-               return PROMDEV_I_UNK;
-
-       switch (propb[3]) {
-               case 'a': return PROMDEV_ITTYA;
-               case 'b': return PROMDEV_ITTYB;
-               default: return PROMDEV_I_UNK;
-       }
-}
-
-/* Query for output device type */
-
-enum prom_output_device
-prom_query_output_device(void)
-{
-       int st_p;
-       char propb[64];
-       int propl;
-
-       st_p = prom_inst2pkg(prom_stdout);
-       propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb));
-       if (propl >= 0 && propl == sizeof("display") &&
-           strncmp("display", propb, sizeof("display")) == 0)
-               return PROMDEV_OSCREEN;
-       if(strncmp("serial", propb, 6))
-               return PROMDEV_O_UNK;
-       /* FIXME: Is there any better way how to find out? */   
-       memset(propb, 0, sizeof(propb));
-       st_p = prom_finddevice ("/options");
-       prom_getproperty(st_p, "output-device", propb, sizeof(propb));
-
-       /*
-        * If we get here with propb == 'screen', we are on ttya, as
-        * the PROM defaulted to this due to 'no input device'.
-        */
-       if (!strncmp(propb, "screen", 6))
-               return PROMDEV_OTTYA;
-
-       if (!strncmp (propb, "rsc", 3))
-               return PROMDEV_ORSC;
-
-       if (!strncmp (propb, "virtual-console", 3))
-               return PROMDEV_OVCONS;
-
-       if (strncmp (propb, "tty", 3) || !propb[3])
-               return PROMDEV_O_UNK;
-
-       switch (propb[3]) {
-               case 'a': return PROMDEV_OTTYA;
-               case 'b': return PROMDEV_OTTYB;
-               default: return PROMDEV_O_UNK;
-       }
-}
index 33c5b7da31e5522906855441953caa933d5ec835..68c83ad04ad958651654e6439657206284ae5df8 100644 (file)
@@ -72,7 +72,7 @@ void prom_cmdline(void)
 
        local_irq_save(flags);
 
-       if (!serial_console && prom_palette)
+       if (prom_palette)
                prom_palette(1);
 
 #ifdef CONFIG_SMP
@@ -85,7 +85,7 @@ void prom_cmdline(void)
        smp_release();
 #endif
 
-       if (!serial_console && prom_palette)
+       if (prom_palette)
                prom_palette(0);
 
        local_irq_restore(flags);
index 17b7ecfe7ca95aed84232c40020509a50f48ddf6..b2c5b12c9818ad57f5602491865f84b2898c970e 100644 (file)
@@ -304,3 +304,11 @@ prom_pathtoinode(const char *path)
        if (node == -1) return 0;
        return node;
 }
+
+int prom_ihandle2path(int handle, char *buffer, int bufsize)
+{
+       return p1275_cmd("instance-to-path",
+                        P1275_ARG(1,P1275_ARG_OUT_BUF)|
+                        P1275_INOUT(3, 1),
+                        handle, buffer, P1275_SIZE(bufsize));
+}
index b45ba5392dd362941e12770edcf12c5671e590b2..70a09a3d5af0ee6999b98a57d766f4420688d94c 100644 (file)
 #include <linux/tty.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/serial_core.h>
 #include <linux/init.h>
 
-#include <asm/oplib.h>
+#include <asm/prom.h>
 
 #include "suncore.h"
 
@@ -26,92 +27,60 @@ int sunserial_current_minor = 64;
 
 EXPORT_SYMBOL(sunserial_current_minor);
 
-void
-sunserial_console_termios(struct console *con)
+int sunserial_console_match(struct console *con, struct device_node *dp,
+                           struct uart_driver *drv, int line)
 {
-       char mode[16], buf[16], *s;
-       char mode_prop[] = "ttyX-mode";
-       char cd_prop[]   = "ttyX-ignore-cd";
-       char dtr_prop[]  = "ttyX-rts-dtr-off";
-       char *ssp_console_modes_prop = "ssp-console-modes";
-       int baud, bits, stop, cflag;
-       char parity;
-       int carrier = 0;
-       int rtsdtr = 1;
-       int topnd, nd;
-
-       if (!serial_console)
-               return;
-
-       switch (serial_console) {
-       case PROMDEV_OTTYA:
-               mode_prop[3] = 'a';
-               cd_prop[3] = 'a';
-               dtr_prop[3] = 'a';
-               break;
-
-       case PROMDEV_OTTYB:
-               mode_prop[3] = 'b';
-               cd_prop[3] = 'b';
-               dtr_prop[3] = 'b';
-               break;
-
-       case PROMDEV_ORSC:
-
-               nd = prom_pathtoinode("rsc");
-               if (!nd) {
-                       strcpy(mode, "115200,8,n,1,-");
-                       goto no_options;
-               }
+       int off;
 
-               if (!prom_node_has_property(nd, ssp_console_modes_prop)) {
-                       strcpy(mode, "115200,8,n,1,-");
-                       goto no_options;
-               }
+       if (!con || of_console_device != dp)
+               return 0;
 
-               memset(mode, 0, sizeof(mode));
-               prom_getstring(nd, ssp_console_modes_prop, mode, sizeof(mode));
-               goto no_options;
+       off = 0;
+       if (of_console_options &&
+           *of_console_options == 'b')
+               off = 1;
 
-       default:
-               strcpy(mode, "9600,8,n,1,-");
-               goto no_options;
-       }
+       if ((line & 1) != off)
+               return 0;
 
-       topnd = prom_getchild(prom_root_node);
-       nd = prom_searchsiblings(topnd, "options");
-       if (!nd) {
-               strcpy(mode, "9600,8,n,1,-");
-               goto no_options;
-       }
-
-       if (!prom_node_has_property(nd, mode_prop)) {
-               strcpy(mode, "9600,8,n,1,-");
-               goto no_options;
-       }
+       con->index = line;
+       drv->cons = con;
+       add_preferred_console(con->name, line, NULL);
 
-       memset(mode, 0, sizeof(mode));
-       prom_getstring(nd, mode_prop, mode, sizeof(mode));
-
-       if (prom_node_has_property(nd, cd_prop)) {
-               memset(buf, 0, sizeof(buf));
-               prom_getstring(nd, cd_prop, buf, sizeof(buf));
-               if (!strcmp(buf, "false"))
-                       carrier = 1;
-
-               /* XXX: this is unused below. */
-       }
+       return 1;
+}
+EXPORT_SYMBOL(sunserial_console_match);
 
-       if (prom_node_has_property(nd, dtr_prop)) {
-               memset(buf, 0, sizeof(buf));
-               prom_getstring(nd, dtr_prop, buf, sizeof(buf));
-               if (!strcmp(buf, "false"))
-                       rtsdtr = 0;
+void
+sunserial_console_termios(struct console *con)
+{
+       struct device_node *dp;
+       const char *od, *mode, *s;
+       char mode_prop[] = "ttyX-mode";
+       int baud, bits, stop, cflag;
+       char parity;
 
-               /* XXX: this is unused below. */
+       dp = of_find_node_by_path("/options");
+       od = of_get_property(dp, "output-device", NULL);
+       if (!strcmp(od, "rsc")) {
+               mode = of_get_property(of_console_device,
+                                      "ssp-console-modes", NULL);
+               if (!mode)
+                       mode = "115200,8,n,1,-";
+       } else {
+               char c;
+
+               c = 'a';
+               if (of_console_options)
+                       c = *of_console_options;
+
+               mode_prop[3] = c;
+
+               mode = of_get_property(dp, mode_prop, NULL);
+               if (!mode)
+                       mode = "9600,8,n,1,-";
        }
 
-no_options:
        cflag = CREAD | HUPCL | CLOCAL;
 
        s = mode;
index 513916a8ce376f4f25796be7ac8bd942f38ef4ef..829d7d65d6dbf4dec55e8992a8d77a795b0b02d2 100644 (file)
@@ -24,6 +24,8 @@ extern int suncore_mouse_baud_detection(unsigned char, int);
 
 extern int sunserial_current_minor;
 
+extern int sunserial_console_match(struct console *, struct device_node *,
+                                  struct uart_driver *, int);
 extern void sunserial_console_termios(struct console *);
 
 #endif /* !(_SERIAL_SUN_H) */
index d82be42ff29acf2f17b490f93beefc00f40fff54..8ff900b098116ebc7c54f4b5ec676223fe4cf54b 100644 (file)
@@ -520,16 +520,6 @@ static struct console sunhv_console = {
        .data   =       &sunhv_reg,
 };
 
-static inline struct console *SUNHV_CONSOLE(void)
-{
-       if (con_is_present())
-               return NULL;
-
-       sunhv_console.index = 0;
-
-       return &sunhv_console;
-}
-
 static int __devinit hv_probe(struct of_device *op, const struct of_device_id *match)
 {
        struct uart_port *port;
@@ -582,7 +572,8 @@ static int __devinit hv_probe(struct of_device *op, const struct of_device_id *m
        sunhv_reg.tty_driver->name_base = sunhv_reg.minor - 64;
        sunserial_current_minor += 1;
 
-       sunhv_reg.cons = SUNHV_CONSOLE();
+       sunserial_console_match(&sunhv_console, op->node,
+                               &sunhv_reg, port->line);
 
        err = uart_add_one_port(&sunhv_reg, port);
        if (err)
index 8a0f9e4408d4a78976040178885efc1571b7a184..bca57bb949393275c902f5f31e35e1abe9527d1a 100644 (file)
@@ -968,22 +968,6 @@ static struct console sunsab_console = {
 
 static inline struct console *SUNSAB_CONSOLE(void)
 {
-       int i;
-
-       if (con_is_present())
-               return NULL;
-
-       for (i = 0; i < num_channels; i++) {
-               int this_minor = sunsab_reg.minor + i;
-
-               if ((this_minor - 64) == (serial_console - 1))
-                       break;
-       }
-       if (i == num_channels)
-               return NULL;
-
-       sunsab_console.index = i;
-
        return &sunsab_console;
 }
 #else
@@ -1080,7 +1064,12 @@ static int __devinit sab_probe(struct of_device *op, const struct of_device_id *
                return err;
        }
 
+       sunserial_console_match(SUNSAB_CONSOLE(), op->node,
+                               &sunsab_reg, up[0].port.line);
        uart_add_one_port(&sunsab_reg, &up[0].port);
+
+       sunserial_console_match(SUNSAB_CONSOLE(), op->node,
+                               &sunsab_reg, up[1].port.line);
        uart_add_one_port(&sunsab_reg, &up[1].port);
 
        dev_set_drvdata(&op->dev, &up[0]);
@@ -1164,7 +1153,6 @@ static int __init sunsab_init(void)
                }
 
                sunsab_reg.tty_driver->name_base = sunsab_reg.minor - 64;
-               sunsab_reg.cons = SUNSAB_CONSOLE();
                sunserial_current_minor += num_channels;
        }
 
index 26d720baf88c17619577d09420b50cade271e09d..79b13685bdfa45b7dc12f583f1486492f06c7992 100644 (file)
@@ -1371,28 +1371,12 @@ static struct console sunsu_console = {
  *     Register console.
  */
 
-static inline struct console *SUNSU_CONSOLE(int num_uart)
+static inline struct console *SUNSU_CONSOLE(void)
 {
-       int i;
-
-       if (con_is_present())
-               return NULL;
-
-       for (i = 0; i < num_uart; i++) {
-               int this_minor = sunsu_reg.minor + i;
-
-               if ((this_minor - 64) == (serial_console - 1))
-                       break;
-       }
-       if (i == num_uart)
-               return NULL;
-
-       sunsu_console.index = i;
-
        return &sunsu_console;
 }
 #else
-#define SUNSU_CONSOLE(num_uart)                (NULL)
+#define SUNSU_CONSOLE()                        (NULL)
 #define sunsu_serial_console_init()    do { } while (0)
 #endif
 
@@ -1482,6 +1466,8 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m
 
        up->port.ops = &sunsu_pops;
 
+       sunserial_console_match(SUNSU_CONSOLE(), dp,
+                               &sunsu_reg, up->port.line);
        err = uart_add_one_port(&sunsu_reg, &up->port);
        if (err)
                goto out_unmap;
@@ -1572,7 +1558,6 @@ static int __init sunsu_init(void)
                        return err;
                sunsu_reg.tty_driver->name_base = sunsu_reg.minor - 64;
                sunserial_current_minor += num_uart;
-               sunsu_reg.cons = SUNSU_CONSOLE(num_uart);
        }
 
        err = of_register_driver(&su_driver, &of_bus_type);
index 0a3e10a4a35dec59485e1455b5ee8f30a0277c25..1d262c0c613fadbebddde44548d167eb9ec322ce 100644 (file)
@@ -1226,23 +1226,6 @@ static struct console sunzilog_console_ops = {
 
 static inline struct console *SUNZILOG_CONSOLE(void)
 {
-       int i;
-
-       if (con_is_present())
-               return NULL;
-
-       for (i = 0; i < NUM_CHANNELS; i++) {
-               int this_minor = sunzilog_reg.minor + i;
-
-               if ((this_minor - 64) == (serial_console - 1))
-                       break;
-       }
-       if (i == NUM_CHANNELS)
-               return NULL;
-
-       sunzilog_console_ops.index = i;
-       sunzilog_port_table[i].flags |= SUNZILOG_FLAG_IS_CONS;
-
        return &sunzilog_console_ops;
 }
 
@@ -1428,12 +1411,18 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m
        sunzilog_init_hw(&up[1]);
 
        if (!keyboard_mouse) {
+               if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node,
+                                           &sunzilog_reg, up[0].port.line))
+                       up->flags |= SUNZILOG_FLAG_IS_CONS;
                err = uart_add_one_port(&sunzilog_reg, &up[0].port);
                if (err) {
                        of_iounmap(&op->resource[0],
                                   rp, sizeof(struct zilog_layout));
                        return err;
                }
+               if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node,
+                                           &sunzilog_reg, up[1].port.line))
+                       up->flags |= SUNZILOG_FLAG_IS_CONS;
                err = uart_add_one_port(&sunzilog_reg, &up[1].port);
                if (err) {
                        uart_remove_one_port(&sunzilog_reg, &up[0].port);
@@ -1531,7 +1520,6 @@ static int __init sunzilog_init(void)
                        goto out_free_tables;
 
                sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64;
-               sunzilog_reg.cons = SUNZILOG_CONSOLE();
 
                sunserial_current_minor += uart_count;
        }
index 0c7bf75732ea8d8a3e29c087288593baeb2318f9..13990697b5c12a76e41cd31fdc37873bebcbc2d5 100644 (file)
@@ -2913,10 +2913,6 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
        int node, len, i, j, ret;
        u32 mem, chip_id;
 
-       /* Do not attach when we have a serial console. */
-       if (!con_is_present())
-               return -ENXIO;
-
        /*
         * Map memory-mapped registers.
         */
index eb1a4812ad1d27b471dd61bcfbaac5ba54b2630d..b87ea21d3d78480faeca4bdc5f06d71aea4fe2b6 100644 (file)
@@ -379,10 +379,6 @@ int __init igafb_init(void)
        if (fb_get_options("igafb", NULL))
                return -ENODEV;
 
-        /* Do not attach when we have a serial console. */
-        if (!con_is_present())
-                return -ENXIO;
-
         pdev = pci_get_device(PCI_VENDOR_ID_INTERG,
                                PCI_DEVICE_ID_INTERG_1682, 0);
        if (pdev == NULL) {
index 91691e52c058340047fef1eb08f4cb43b49376ee..17ba82ee220a791c40b13d4079ab607c11f4c2a4 100644 (file)
@@ -158,32 +158,6 @@ extern void prom_putchar(char character);
 extern void prom_printf(char *fmt, ...);
 extern void prom_write(const char *buf, unsigned int len);
 
-/* Query for input device type */
-
-enum prom_input_device {
-       PROMDEV_IKBD,                   /* input from keyboard */
-       PROMDEV_ITTYA,                  /* input from ttya */
-       PROMDEV_ITTYB,                  /* input from ttyb */
-       PROMDEV_IRSC,                   /* input from rsc */
-       PROMDEV_IVCONS,                 /* input from virtual-console */
-       PROMDEV_I_UNK,
-};
-
-extern enum prom_input_device prom_query_input_device(void);
-
-/* Query for output device type */
-
-enum prom_output_device {
-       PROMDEV_OSCREEN,                /* to screen */
-       PROMDEV_OTTYA,                  /* to ttya */
-       PROMDEV_OTTYB,                  /* to ttyb */
-       PROMDEV_ORSC,                   /* to rsc */
-       PROMDEV_OVCONS,                 /* to virtual-console */
-       PROMDEV_O_UNK,
-};
-
-extern enum prom_output_device prom_query_output_device(void);
-
 /* Multiprocessor operations... */
 
 /* Start the CPU with the given device tree node, context table, and context
index db9feb75bd86f0713b26fe09edd366abefc8c80e..350676c589f9d05c6bb659334441b2335f391908 100644 (file)
@@ -85,5 +85,9 @@ static inline void of_node_put(struct device_node *node)
  */
 #include <linux/of.h>
 
+extern struct device_node *of_console_device;
+extern char *of_console_path;
+extern char *of_console_options;
+
 #endif /* __KERNEL__ */
 #endif /* _SPARC_PROM_H */
index 992f9f7a476cef4e79fa7dee9403d1e835ddf0c9..3f23c5dc5f2140040db7c13bc66774c0954ce08d 100644 (file)
@@ -140,32 +140,6 @@ extern void prom_putchar(char character);
 extern void prom_printf(const char *fmt, ...);
 extern void prom_write(const char *buf, unsigned int len);
 
-/* Query for input device type */
-
-enum prom_input_device {
-       PROMDEV_IKBD,                   /* input from keyboard */
-       PROMDEV_ITTYA,                  /* input from ttya */
-       PROMDEV_ITTYB,                  /* input from ttyb */
-       PROMDEV_IRSC,                   /* input from rsc */
-       PROMDEV_IVCONS,                 /* input from virtual-console */
-       PROMDEV_I_UNK,
-};
-
-extern enum prom_input_device prom_query_input_device(void);
-
-/* Query for output device type */
-
-enum prom_output_device {
-       PROMDEV_OSCREEN,                /* to screen */
-       PROMDEV_OTTYA,                  /* to ttya */
-       PROMDEV_OTTYB,                  /* to ttyb */
-       PROMDEV_ORSC,                   /* to rsc */
-       PROMDEV_OVCONS,                 /* to virtual-console */
-       PROMDEV_O_UNK,
-};
-
-extern enum prom_output_device prom_query_output_device(void);
-
 /* Multiprocessor operations... */
 #ifdef CONFIG_SMP
 /* Start the CPU with the given device tree node at the passed program
@@ -319,6 +293,8 @@ extern int prom_inst2pkg(int);
 extern int prom_service_exists(const char *service_name);
 extern void prom_sun4v_guest_soft_state(void);
 
+extern int prom_ihandle2path(int handle, char *buffer, int bufsize);
+
 /* Client interface level routines. */
 extern void prom_set_trap_table(unsigned long tba);
 extern void prom_set_trap_table_sun4v(unsigned long tba, unsigned long mmfsa);
index 2b9e0d795faf7d1ddfbe360589947f4c6e4b8c55..31dcb92fbae0cc27039c33c189c3f73d2730a09a 100644 (file)
@@ -94,5 +94,9 @@ static inline void of_node_put(struct device_node *node)
  */
 #include <linux/of.h>
 
+extern struct device_node *of_console_device;
+extern char *of_console_path;
+extern char *of_console_options;
+
 #endif /* __KERNEL__ */
 #endif /* _SPARC64_PROM_H */
index 409067408eec07504db76532dd75b213c51d5177..64891cb10f05c572c6ec1e9a86f0eef14271a4b9 100644 (file)
@@ -115,14 +115,8 @@ do {       __asm__ __volatile__("ba,pt     %%xcc, 1f\n\t" \
 #ifndef __ASSEMBLY__
 
 extern void sun_do_break(void);
-extern int serial_console;
 extern int stop_a_enabled;
 
-static __inline__ int con_is_present(void)
-{
-       return serial_console ? 0 : 1;
-}
-
 extern void synchronize_user_stack(void);
 
 extern void __flushw_user(void);