Commit 4371c631 authored by Keith M. Wesolowski's avatar Keith M. Wesolowski

[SPARC]: Fix serial console selection.

Add a generic add_preferred_console() to printk.c so that other
platforms, such as MIPS for example, can sanely fix this problem
as well.
parent babdc53e
...@@ -105,8 +105,6 @@ unsigned int boot_flags __initdata = 0; ...@@ -105,8 +105,6 @@ unsigned int boot_flags __initdata = 0;
#define BOOTME_DEBUG 0x1 #define BOOTME_DEBUG 0x1
#define BOOTME_SINGLE 0x2 #define BOOTME_SINGLE 0x2
static int console_fb __initdata = 0;
/* Exported for mm/init.c:paging_init. */ /* Exported for mm/init.c:paging_init. */
unsigned long cmdline_memory_size __initdata = 0; unsigned long cmdline_memory_size __initdata = 0;
...@@ -160,6 +158,31 @@ static void __init process_switch(char c) ...@@ -160,6 +158,31 @@ 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) static void __init boot_flags_init(char *commands)
{ {
while (*commands) { while (*commands) {
...@@ -174,37 +197,27 @@ static void __init boot_flags_init(char *commands) ...@@ -174,37 +197,27 @@ static void __init boot_flags_init(char *commands)
commands++; commands++;
while (*commands && *commands != ' ') while (*commands && *commands != ' ')
process_switch(*commands++); process_switch(*commands++);
} else { continue;
if (!strncmp(commands, "console=", 8)) { }
commands += 8; if (!strncmp(commands, "console=", 8)) {
#if defined(CONFIG_PROM_CONSOLE) process_console(commands);
if (!strncmp (commands, "prom", 4)) { } else if (!strncmp(commands, "mem=", 4)) {
char *p; /*
* "mem=XXX[kKmM] overrides the PROM-reported
for (p = commands - 8; *p && *p != ' '; p++) * memory size.
*p = ' '; */
conswitchp = &prom_con; cmdline_memory_size = simple_strtoul(commands + 4,
console_fb = 1; &commands, 0);
} if (*commands == 'K' || *commands == 'k') {
#endif cmdline_memory_size <<= 10;
} else if (!strncmp(commands, "mem=", 4)) { commands++;
/* } else if (*commands=='M' || *commands=='m') {
* "mem=XXX[kKmM] overrides the PROM-reported cmdline_memory_size <<= 20;
* memory size.
*/
cmdline_memory_size = simple_strtoul(commands + 4,
&commands, 0);
if (*commands == 'K' || *commands == 'k') {
cmdline_memory_size <<= 10;
commands++;
} else if (*commands=='M' || *commands=='m') {
cmdline_memory_size <<= 20;
commands++;
}
}
while (*commands && *commands != ' ')
commands++; commands++;
}
} }
while (*commands && *commands != ' ')
commands++;
} }
} }
...@@ -330,34 +343,6 @@ void __init setup_arch(char **cmdline_p) ...@@ -330,34 +343,6 @@ void __init setup_arch(char **cmdline_p)
prom_setsync(prom_sync_me); prom_setsync(prom_sync_me);
#ifndef CONFIG_SERIAL_CONSOLE /* Not CONFIG_SERIAL_SUNCORE: to be gone. */
serial_console = 0;
#else
if (console_fb != 0) {
serial_console = 0;
} else {
int idev = prom_query_input_device();
int 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;
}
}
#endif
if((boot_flags&BOOTME_DEBUG) && (linux_dbvec!=0) && if((boot_flags&BOOTME_DEBUG) && (linux_dbvec!=0) &&
((*(short *)linux_dbvec) != -1)) { ((*(short *)linux_dbvec) != -1)) {
printk("Booted under KADB. Syncing trap table.\n"); printk("Booted under KADB. Syncing trap table.\n");
...@@ -370,6 +355,41 @@ void __init setup_arch(char **cmdline_p) ...@@ -370,6 +355,41 @@ void __init setup_arch(char **cmdline_p)
paging_init(); 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_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);
asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on) asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
{ {
return -EIO; return -EIO;
...@@ -458,5 +478,5 @@ void sun_do_break(void) ...@@ -458,5 +478,5 @@ void sun_do_break(void)
prom_cmdline(); prom_cmdline();
} }
int serial_console; int serial_console = -1;
int stop_a_enabled = 1; int stop_a_enabled = 1;
...@@ -320,8 +320,6 @@ unsigned int boot_flags = 0; ...@@ -320,8 +320,6 @@ unsigned int boot_flags = 0;
#define BOOTME_DEBUG 0x1 #define BOOTME_DEBUG 0x1
#define BOOTME_SINGLE 0x2 #define BOOTME_SINGLE 0x2
static int console_fb __initdata = 0;
/* Exported for mm/init.c:paging_init. */ /* Exported for mm/init.c:paging_init. */
unsigned long cmdline_memory_size = 0; unsigned long cmdline_memory_size = 0;
...@@ -374,6 +372,33 @@ static void __init process_switch(char c) ...@@ -374,6 +372,33 @@ 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) static void __init boot_flags_init(char *commands)
{ {
while (*commands) { while (*commands) {
...@@ -384,49 +409,31 @@ static void __init boot_flags_init(char *commands) ...@@ -384,49 +409,31 @@ static void __init boot_flags_init(char *commands)
/* Process any command switches, otherwise skip it. */ /* Process any command switches, otherwise skip it. */
if (*commands == '\0') if (*commands == '\0')
break; break;
else if (*commands == '-') { if (*commands == '-') {
commands++; commands++;
while (*commands && *commands != ' ') while (*commands && *commands != ' ')
process_switch(*commands++); process_switch(*commands++);
} else { continue;
if (!strncmp(commands, "console=", 8)) { }
commands += 8; if (!strncmp(commands, "console=", 8)) {
if (!strncmp (commands, "ttya", 4)) { process_console(commands);
console_fb = 2; } else if (!strncmp(commands, "mem=", 4)) {
prom_printf ("Using /dev/ttya as console.\n"); /*
} else if (!strncmp (commands, "ttyb", 4)) { * "mem=XXX[kKmM]" overrides the PROM-reported
console_fb = 3; * memory size.
prom_printf ("Using /dev/ttyb as console.\n"); */
#if defined(CONFIG_PROM_CONSOLE) cmdline_memory_size = simple_strtoul(commands + 4,
} else if (!strncmp (commands, "prom", 4)) { &commands, 0);
char *p; if (*commands == 'K' || *commands == 'k') {
cmdline_memory_size <<= 10;
for (p = commands - 8; *p && *p != ' '; p++) commands++;
*p = ' '; } else if (*commands=='M' || *commands=='m') {
conswitchp = &prom_con; cmdline_memory_size <<= 20;
console_fb = 1;
#endif
} else {
console_fb = 1;
}
} else if (!strncmp(commands, "mem=", 4)) {
/*
* "mem=XXX[kKmM]" overrides the PROM-reported
* memory size.
*/
cmdline_memory_size = simple_strtoul(commands + 4,
&commands, 0);
if (*commands == 'K' || *commands == 'k') {
cmdline_memory_size <<= 10;
commands++;
} else if (*commands=='M' || *commands=='m') {
cmdline_memory_size <<= 20;
commands++;
}
}
while (*commands && *commands != ' ')
commands++; commands++;
}
} }
while (*commands && *commands != ' ')
commands++;
} }
} }
...@@ -546,38 +553,38 @@ void __init setup_arch(char **cmdline_p) ...@@ -546,38 +553,38 @@ void __init setup_arch(char **cmdline_p)
} }
#endif #endif
switch (console_fb) { paging_init();
case 0: /* Let's get our io devices from prom */ }
{
int idev = prom_query_input_device(); static int __init set_preferred_console(void)
int odev = prom_query_output_device(); {
if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) { int idev, odev;
serial_console = 0;
} else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) { /* The user has requested a console so this is already set up. */
serial_console = 1; if (serial_console >= 0)
} else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) { return -EBUSY;
serial_console = 2;
} else { idev = prom_query_input_device();
prom_printf("Inconsistent console: " odev = prom_query_output_device();
"input %d, output %d\n", if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) {
idev, odev);
prom_halt();
}
}
break;
case 1: /* Force one of the framebuffers as console */
serial_console = 0; serial_console = 0;
break; } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) {
case 2: /* Force ttya as console */
serial_console = 1; serial_console = 1;
break; } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) {
case 3: /* Force ttyb as console */
serial_console = 2; serial_console = 2;
break; } else {
}; prom_printf("Inconsistent console: "
"input %d, output %d\n",
idev, odev);
prom_halt();
}
paging_init(); if (serial_console)
return add_preferred_console("ttyS", serial_console - 1, NULL);
return -ENODEV;
} }
console_initcall(set_preferred_console);
asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on) asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
{ {
...@@ -671,7 +678,7 @@ void sun_do_break(void) ...@@ -671,7 +678,7 @@ void sun_do_break(void)
prom_cmdline(); prom_cmdline();
} }
int serial_console; int serial_console = -1;
int stop_a_enabled = 1; int stop_a_enabled = 1;
static int __init topology_init(void) static int __init topology_init(void)
......
...@@ -97,9 +97,6 @@ struct uart_sunsu_port { ...@@ -97,9 +97,6 @@ struct uart_sunsu_port {
int port_node; int port_node;
unsigned int irq; unsigned int irq;
/* L1-A keyboard break state. */
int kbd_id;
int l1_down;
#ifdef CONFIG_SERIO #ifdef CONFIG_SERIO
struct serio serio; struct serio serio;
int serio_open; int serio_open;
...@@ -508,25 +505,8 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg ...@@ -508,25 +505,8 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg
do { do {
unsigned char ch = serial_inp(up, UART_RX); unsigned char ch = serial_inp(up, UART_RX);
/* Stop-A is handled by drivers/char/keyboard.c now. */
if (up->su_type == SU_PORT_KBD) { if (up->su_type == SU_PORT_KBD) {
if (ch == SUNKBD_RESET) {
up->kbd_id = 1;
up->l1_down = 0;
} else if (up->kbd_id) {
up->kbd_id = 0;
} else if (ch == SUNKBD_L1) {
up->l1_down = 1;
} else if (ch == (SUNKBD_L1|SUNKBD_UP)) {
up->l1_down = 0;
} else if (ch == SUNKBD_A && up->l1_down) {
/* whee... */
sun_do_break();
/* Continue execution... */
up->l1_down = 0;
up->kbd_id = 0;
return;
}
#ifdef CONFIG_SERIO #ifdef CONFIG_SERIO
serio_interrupt(&up->serio, ch, 0, regs); serio_interrupt(&up->serio, ch, 0, regs);
#endif #endif
......
...@@ -103,10 +103,6 @@ struct uart_sunzilog_port { ...@@ -103,10 +103,6 @@ struct uart_sunzilog_port {
unsigned int cflag; unsigned int cflag;
/* L1-A keyboard break state. */
int kbd_id;
int l1_down;
unsigned char parity_mask; unsigned char parity_mask;
unsigned char prev_status; unsigned char prev_status;
...@@ -292,22 +288,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up, ...@@ -292,22 +288,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
struct pt_regs *regs) struct pt_regs *regs)
{ {
if (ZS_IS_KEYB(up)) { if (ZS_IS_KEYB(up)) {
/* if (!serial_console) XXX Keith's case #1 - two brks work */ /* Stop-A is handled by drivers/char/keyboard.c now. */
if (ch == SUNKBD_RESET) {
up->kbd_id = 1;
up->l1_down = 0;
} else if (up->kbd_id) {
up->kbd_id = 0;
} else if (ch == SUNKBD_L1) {
up->l1_down = 1;
} else if (ch == (SUNKBD_L1 | SUNKBD_UP)) {
up->l1_down = 0;
} else if (ch == SUNKBD_A && up->l1_down) {
sun_do_break();
up->l1_down = 0;
up->kbd_id = 0;
return;
}
#ifdef CONFIG_SERIO #ifdef CONFIG_SERIO
if (up->serio_open) if (up->serio_open)
serio_interrupt(&up->serio, ch, 0, regs); serio_interrupt(&up->serio, ch, 0, regs);
......
...@@ -70,18 +70,6 @@ void give_up_console(const struct consw *sw); ...@@ -70,18 +70,6 @@ void give_up_console(const struct consw *sw);
#define CM_ERASE (2) #define CM_ERASE (2)
#define CM_MOVE (3) #define CM_MOVE (3)
/*
* Array of consoles built from command line options (console=)
*/
struct console_cmdline
{
char name[8]; /* Name of the driver */
int index; /* Minor dev. to use */
char *options; /* Options for the driver */
};
#define MAX_CMDLINECONSOLES 8
extern struct console_cmdline console_list[MAX_CMDLINECONSOLES];
/* /*
* The interface for a console, or any other device that * The interface for a console, or any other device that
* wants to capture console messages (printer driver?) * wants to capture console messages (printer driver?)
...@@ -106,6 +94,7 @@ struct console ...@@ -106,6 +94,7 @@ struct console
struct console *next; struct console *next;
}; };
extern int add_preferred_console(char *name, int idx, char *options);
extern void register_console(struct console *); extern void register_console(struct console *);
extern int unregister_console(struct console *); extern int unregister_console(struct console *);
extern struct console *console_drivers; extern struct console *console_drivers;
......
...@@ -86,7 +86,19 @@ static unsigned long con_start; /* Index into log_buf: next char to be sent to c ...@@ -86,7 +86,19 @@ static unsigned long con_start; /* Index into log_buf: next char to be sent to c
static unsigned long log_end; /* Index into log_buf: most-recently-written-char + 1 */ static unsigned long log_end; /* Index into log_buf: most-recently-written-char + 1 */
static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */ static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */
struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES]; /*
* Array of consoles built from command line options (console=)
*/
struct console_cmdline
{
char name[8]; /* Name of the driver */
int index; /* Minor dev. to use */
char *options; /* Options for the driver */
};
#define MAX_CMDLINECONSOLES 8
static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
static int preferred_console = -1; static int preferred_console = -1;
/* Flag: console code may call schedule() */ /* Flag: console code may call schedule() */
...@@ -97,10 +109,9 @@ static int console_may_schedule; ...@@ -97,10 +109,9 @@ static int console_may_schedule;
*/ */
static int __init console_setup(char *str) static int __init console_setup(char *str)
{ {
struct console_cmdline *c; char name[sizeof(console_cmdline[0].name)];
char name[sizeof(c->name)];
char *s, *options; char *s, *options;
int i, idx; int idx;
/* /*
* Decode str into name, index, options. * Decode str into name, index, options.
...@@ -125,6 +136,27 @@ static int __init console_setup(char *str) ...@@ -125,6 +136,27 @@ static int __init console_setup(char *str)
idx = simple_strtoul(s, NULL, 10); idx = simple_strtoul(s, NULL, 10);
*s = 0; *s = 0;
add_preferred_console(name, idx, options);
return 1;
}
__setup("console=", console_setup);
/**
* add_preferred_console - add a device to the list of preferred consoles.
*
* The last preferred console added will be used for kernel messages
* and stdin/out/err for init. Normally this is used by console_setup
* above to handle user-supplied console arguments; however it can also
* be used by arch-specific code either to override the user or more
* commonly to provide a default console (ie from PROM variables) when
* the user has not supplied one.
*/
int __init add_preferred_console(char *name, int idx, char *options)
{
struct console_cmdline *c;
int i;
/* /*
* See if this tty is not yet registered, and * See if this tty is not yet registered, and
* if we have a slot free. * if we have a slot free.
...@@ -133,20 +165,19 @@ static int __init console_setup(char *str) ...@@ -133,20 +165,19 @@ static int __init console_setup(char *str)
if (strcmp(console_cmdline[i].name, name) == 0 && if (strcmp(console_cmdline[i].name, name) == 0 &&
console_cmdline[i].index == idx) { console_cmdline[i].index == idx) {
preferred_console = i; preferred_console = i;
return 1; return 0;
} }
if (i == MAX_CMDLINECONSOLES) if (i == MAX_CMDLINECONSOLES)
return 1; return -E2BIG;
preferred_console = i; preferred_console = i;
c = &console_cmdline[i]; c = &console_cmdline[i];
memcpy(c->name, name, sizeof(c->name)); memcpy(c->name, name, sizeof(c->name));
c->name[sizeof(c->name) - 1] = 0;
c->options = options; c->options = options;
c->index = idx; c->index = idx;
return 1; return 0;
} }
__setup("console=", console_setup);
static int __init log_buf_len_setup(char *str) static int __init log_buf_len_setup(char *str)
{ {
unsigned long size = memparse(str, &str); unsigned long size = memparse(str, &str);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment