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;
#define BOOTME_DEBUG 0x1
#define BOOTME_SINGLE 0x2
static int console_fb __initdata = 0;
/* Exported for mm/init.c:paging_init. */
unsigned long cmdline_memory_size __initdata = 0;
......@@ -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)
{
while (*commands) {
......@@ -174,37 +197,27 @@ static void __init boot_flags_init(char *commands)
commands++;
while (*commands && *commands != ' ')
process_switch(*commands++);
} else {
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
} 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 != ' ')
continue;
}
if (!strncmp(commands, "console=", 8)) {
process_console(commands);
} 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++;
}
}
......@@ -330,34 +343,6 @@ void __init setup_arch(char **cmdline_p)
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) &&
((*(short *)linux_dbvec) != -1)) {
printk("Booted under KADB. Syncing trap table.\n");
......@@ -370,6 +355,41 @@ 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_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)
{
return -EIO;
......@@ -458,5 +478,5 @@ void sun_do_break(void)
prom_cmdline();
}
int serial_console;
int serial_console = -1;
int stop_a_enabled = 1;
......@@ -320,8 +320,6 @@ unsigned int boot_flags = 0;
#define BOOTME_DEBUG 0x1
#define BOOTME_SINGLE 0x2
static int console_fb __initdata = 0;
/* Exported for mm/init.c:paging_init. */
unsigned long cmdline_memory_size = 0;
......@@ -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)
{
while (*commands) {
......@@ -384,49 +409,31 @@ static void __init boot_flags_init(char *commands)
/* Process any command switches, otherwise skip it. */
if (*commands == '\0')
break;
else if (*commands == '-') {
if (*commands == '-') {
commands++;
while (*commands && *commands != ' ')
process_switch(*commands++);
} else {
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;
}
} 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 != ' ')
continue;
}
if (!strncmp(commands, "console=", 8)) {
process_console(commands);
} 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++;
}
}
......@@ -546,38 +553,38 @@ void __init setup_arch(char **cmdline_p)
}
#endif
switch (console_fb) {
case 0: /* Let's get our io devices from prom */
{
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 {
prom_printf("Inconsistent console: "
"input %d, output %d\n",
idev, odev);
prom_halt();
}
}
break;
case 1: /* Force one of the framebuffers as console */
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;
break;
case 2: /* Force ttya as console */
} else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) {
serial_console = 1;
break;
case 3: /* Force ttyb as console */
} else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) {
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)
{
......@@ -671,7 +678,7 @@ void sun_do_break(void)
prom_cmdline();
}
int serial_console;
int serial_console = -1;
int stop_a_enabled = 1;
static int __init topology_init(void)
......
......@@ -97,9 +97,6 @@ struct uart_sunsu_port {
int port_node;
unsigned int irq;
/* L1-A keyboard break state. */
int kbd_id;
int l1_down;
#ifdef CONFIG_SERIO
struct serio serio;
int serio_open;
......@@ -508,25 +505,8 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg
do {
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 (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
serio_interrupt(&up->serio, ch, 0, regs);
#endif
......
......@@ -103,10 +103,6 @@ struct uart_sunzilog_port {
unsigned int cflag;
/* L1-A keyboard break state. */
int kbd_id;
int l1_down;
unsigned char parity_mask;
unsigned char prev_status;
......@@ -292,22 +288,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
struct pt_regs *regs)
{
if (ZS_IS_KEYB(up)) {
/* if (!serial_console) XXX Keith's case #1 - two brks work */
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;
}
/* Stop-A is handled by drivers/char/keyboard.c now. */
#ifdef CONFIG_SERIO
if (up->serio_open)
serio_interrupt(&up->serio, ch, 0, regs);
......
......@@ -70,18 +70,6 @@ void give_up_console(const struct consw *sw);
#define CM_ERASE (2)
#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
* wants to capture console messages (printer driver?)
......@@ -106,6 +94,7 @@ struct console
struct console *next;
};
extern int add_preferred_console(char *name, int idx, char *options);
extern void register_console(struct console *);
extern int unregister_console(struct console *);
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
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 */
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;
/* Flag: console code may call schedule() */
......@@ -97,10 +109,9 @@ static int console_may_schedule;
*/
static int __init console_setup(char *str)
{
struct console_cmdline *c;
char name[sizeof(c->name)];
char name[sizeof(console_cmdline[0].name)];
char *s, *options;
int i, idx;
int idx;
/*
* Decode str into name, index, options.
......@@ -125,6 +136,27 @@ static int __init console_setup(char *str)
idx = simple_strtoul(s, NULL, 10);
*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
* if we have a slot free.
......@@ -133,20 +165,19 @@ static int __init console_setup(char *str)
if (strcmp(console_cmdline[i].name, name) == 0 &&
console_cmdline[i].index == idx) {
preferred_console = i;
return 1;
return 0;
}
if (i == MAX_CMDLINECONSOLES)
return 1;
return -E2BIG;
preferred_console = i;
c = &console_cmdline[i];
memcpy(c->name, name, sizeof(c->name));
c->name[sizeof(c->name) - 1] = 0;
c->options = options;
c->index = idx;
return 1;
return 0;
}
__setup("console=", console_setup);
static int __init log_buf_len_setup(char *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