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,19 +197,10 @@ static void __init boot_flags_init(char *commands) ...@@ -174,19 +197,10 @@ 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 defined(CONFIG_PROM_CONSOLE)
if (!strncmp (commands, "prom", 4)) {
char *p;
for (p = commands - 8; *p && *p != ' '; p++)
*p = ' ';
conswitchp = &prom_con;
console_fb = 1;
} }
#endif if (!strncmp(commands, "console=", 8)) {
process_console(commands);
} else if (!strncmp(commands, "mem=", 4)) { } else if (!strncmp(commands, "mem=", 4)) {
/* /*
* "mem=XXX[kKmM] overrides the PROM-reported * "mem=XXX[kKmM] overrides the PROM-reported
...@@ -205,7 +219,6 @@ static void __init boot_flags_init(char *commands) ...@@ -205,7 +219,6 @@ static void __init boot_flags_init(char *commands)
while (*commands && *commands != ' ') while (*commands && *commands != ' ')
commands++; commands++;
} }
}
} }
/* This routine will in the future do all the nasty prom stuff /* This routine will in the future do all the nasty prom stuff
...@@ -330,14 +343,28 @@ void __init setup_arch(char **cmdline_p) ...@@ -330,14 +343,28 @@ 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. */ if((boot_flags&BOOTME_DEBUG) && (linux_dbvec!=0) &&
serial_console = 0; ((*(short *)linux_dbvec) != -1)) {
#else printk("Booted under KADB. Syncing trap table.\n");
if (console_fb != 0) { (*(linux_dbvec->teach_debugger))();
serial_console = 0; }
} else {
int idev = prom_query_input_device(); init_mm.context = (unsigned long) NO_CONTEXT;
int odev = prom_query_output_device(); init_task.thread.kregs = &fake_swapper_regs;
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) { if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) {
serial_console = 0; serial_console = 0;
} else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) { } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) {
...@@ -355,20 +382,13 @@ void __init setup_arch(char **cmdline_p) ...@@ -355,20 +382,13 @@ void __init setup_arch(char **cmdline_p)
idev, odev); idev, odev);
serial_console = 1; serial_console = 1;
} }
}
#endif
if((boot_flags&BOOTME_DEBUG) && (linux_dbvec!=0) &&
((*(short *)linux_dbvec) != -1)) {
printk("Booted under KADB. Syncing trap table.\n");
(*(linux_dbvec->teach_debugger))();
}
init_mm.context = (unsigned long) NO_CONTEXT; if (serial_console)
init_task.thread.kregs = &fake_swapper_regs; return add_preferred_console("ttyS", serial_console - 1, NULL);
paging_init(); 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)
{ {
...@@ -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,31 +409,14 @@ static void __init boot_flags_init(char *commands) ...@@ -384,31 +409,14 @@ 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, "ttya", 4)) {
console_fb = 2;
prom_printf ("Using /dev/ttya as console.\n");
} else if (!strncmp (commands, "ttyb", 4)) {
console_fb = 3;
prom_printf ("Using /dev/ttyb as console.\n");
#if defined(CONFIG_PROM_CONSOLE)
} else if (!strncmp (commands, "prom", 4)) {
char *p;
for (p = commands - 8; *p && *p != ' '; p++)
*p = ' ';
conswitchp = &prom_con;
console_fb = 1;
#endif
} else {
console_fb = 1;
} }
if (!strncmp(commands, "console=", 8)) {
process_console(commands);
} else if (!strncmp(commands, "mem=", 4)) { } else if (!strncmp(commands, "mem=", 4)) {
/* /*
* "mem=XXX[kKmM]" overrides the PROM-reported * "mem=XXX[kKmM]" overrides the PROM-reported
...@@ -427,7 +435,6 @@ static void __init boot_flags_init(char *commands) ...@@ -427,7 +435,6 @@ static void __init boot_flags_init(char *commands)
while (*commands && *commands != ' ') while (*commands && *commands != ' ')
commands++; commands++;
} }
}
} }
extern int prom_probe_memory(void); extern int prom_probe_memory(void);
...@@ -546,11 +553,19 @@ void __init setup_arch(char **cmdline_p) ...@@ -546,11 +553,19 @@ 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(); {
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) { if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) {
serial_console = 0; serial_console = 0;
} else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) { } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) {
...@@ -563,21 +578,13 @@ void __init setup_arch(char **cmdline_p) ...@@ -563,21 +578,13 @@ void __init setup_arch(char **cmdline_p)
idev, odev); idev, odev);
prom_halt(); prom_halt();
} }
}
break;
case 1: /* Force one of the framebuffers as console */
serial_console = 0;
break;
case 2: /* Force ttya as console */
serial_console = 1;
break;
case 3: /* Force ttyb as console */
serial_console = 2;
break;
};
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