Modifications to support console multiplexing. This is controlled using CONFIG_SYS_CONSOLE_MUX in the board configuration file. This allows a user to specify multiple console devices in the environment with a command like this: setenv stdin serial,nc. As a result, the user can enter text on both the serial and netconsole interfaces. All devices - stdin, stdout and stderr - can be set in this manner. 1) common/iomux.c and include/iomux.h contain the environment setting implementation. 2) doc/README.iomux contains a somewhat more detailed description. 3) The implementation in (1) is called from common/cmd_nvedit.c to handle setenv and from common/console.c to handle initialization of input/output devices at boot time. 4) common/console.c also contains the code needed to poll multiple console devices for input and send output to all devices registered for output. 5) include/common.h includes iomux.h and common/Makefile generates iomux.o when CONFIG_SYS_CONSOLE_MUX is set. Signed-off-by: Gary Jennejohn <garyj@denx.de>master
parent
774ce72026
commit
16a28ef219
@ -0,0 +1,175 @@ |
|||||||
|
/*
|
||||||
|
* (C) Copyright 2008 |
||||||
|
* Gary Jennejohn, DENX Software Engineering GmbH, garyj@denx.de. |
||||||
|
* |
||||||
|
* See file CREDITS for list of people who contributed to this |
||||||
|
* project. |
||||||
|
* |
||||||
|
* This program is free software; you can redistribute it and/or |
||||||
|
* modify it under the terms of the GNU General Public License as |
||||||
|
* published by the Free Software Foundation; either version 2 of |
||||||
|
* the License, or (at your option) any later version. |
||||||
|
* |
||||||
|
* This program is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
* GNU General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program; if not, write to the Free Software |
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||||
|
* MA 02111-1307 USA |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <common.h> |
||||||
|
#include <serial.h> |
||||||
|
#include <malloc.h> |
||||||
|
|
||||||
|
#ifdef CONFIG_CONSOLE_MUX |
||||||
|
void iomux_printdevs(const int console) |
||||||
|
{ |
||||||
|
int i; |
||||||
|
device_t *dev; |
||||||
|
|
||||||
|
for (i = 0; i < cd_count[console]; i++) { |
||||||
|
dev = console_devices[console][i]; |
||||||
|
printf("%s ", dev->name); |
||||||
|
} |
||||||
|
printf("\n"); |
||||||
|
} |
||||||
|
|
||||||
|
/* This tries to preserve the old list if an error occurs. */ |
||||||
|
int iomux_doenv(const int console, const char *arg) |
||||||
|
{ |
||||||
|
char *console_args, *temp, **start; |
||||||
|
int i, j, k, io_flag, cs_idx, repeat; |
||||||
|
device_t *dev; |
||||||
|
device_t **cons_set; |
||||||
|
|
||||||
|
console_args = strdup(arg); |
||||||
|
if (console_args == NULL) |
||||||
|
return 1; |
||||||
|
/*
|
||||||
|
* Check whether a comma separated list of devices was |
||||||
|
* entered and count how many devices were entered. |
||||||
|
* The array start[] has pointers to the beginning of |
||||||
|
* each device name (up to MAX_CONSARGS devices). |
||||||
|
* |
||||||
|
* Have to do this twice - once to count the number of |
||||||
|
* commas and then again to populate start. |
||||||
|
*/ |
||||||
|
i = 0; |
||||||
|
temp = console_args; |
||||||
|
for (;;) { |
||||||
|
temp = strchr(temp, ','); |
||||||
|
if (temp != NULL) { |
||||||
|
i++; |
||||||
|
temp++; |
||||||
|
continue; |
||||||
|
} |
||||||
|
/* There's always one entry more than the number of commas. */ |
||||||
|
i++; |
||||||
|
break; |
||||||
|
} |
||||||
|
start = (char **)malloc(i * sizeof(char *)); |
||||||
|
if (start == NULL) { |
||||||
|
free(console_args); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
i = 0; |
||||||
|
start[0] = console_args; |
||||||
|
for (;;) { |
||||||
|
temp = strchr(start[i++], ','); |
||||||
|
if (temp == NULL) |
||||||
|
break; |
||||||
|
*temp = '\0'; |
||||||
|
start[i] = temp + 1; |
||||||
|
} |
||||||
|
cons_set = (device_t **)calloc(i, sizeof(device_t *)); |
||||||
|
if (cons_set == NULL) { |
||||||
|
free(start); |
||||||
|
free(console_args); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
switch (console) { |
||||||
|
case stdin: |
||||||
|
io_flag = DEV_FLAGS_INPUT; |
||||||
|
break; |
||||||
|
case stdout: |
||||||
|
case stderr: |
||||||
|
io_flag = DEV_FLAGS_OUTPUT; |
||||||
|
break; |
||||||
|
default: |
||||||
|
free(start); |
||||||
|
free(console_args); |
||||||
|
free(cons_set); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
cs_idx = 0; |
||||||
|
for (j = 0; j < i; j++) { |
||||||
|
/*
|
||||||
|
* Check whether the device exists and is valid. |
||||||
|
* console_assign() also calls search_device(), |
||||||
|
* but I need the pointer to the device. |
||||||
|
*/ |
||||||
|
dev = search_device(io_flag, start[j]); |
||||||
|
if (dev == NULL) |
||||||
|
continue; |
||||||
|
/*
|
||||||
|
* Prevent multiple entries for a device. |
||||||
|
*/ |
||||||
|
repeat = 0; |
||||||
|
for (k = 0; k < cs_idx; k++) { |
||||||
|
if (dev == cons_set[k]) { |
||||||
|
repeat++; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
if (repeat) |
||||||
|
continue; |
||||||
|
/*
|
||||||
|
* Try assigning the specified device. |
||||||
|
* This could screw up the console settings for apps. |
||||||
|
*/ |
||||||
|
if (console_assign(console, start[j]) < 0) |
||||||
|
continue; |
||||||
|
#ifdef CONFIG_SERIAL_MULTI |
||||||
|
/*
|
||||||
|
* This was taken from common/cmd_nvedit.c. |
||||||
|
* This will never work because serial_assign() returns |
||||||
|
* 1 upon error, not -1. |
||||||
|
* This would almost always return an error anyway because |
||||||
|
* serial_assign() expects the name of a serial device, like |
||||||
|
* serial_smc, but the user generally only wants to set serial. |
||||||
|
*/ |
||||||
|
if (serial_assign(start[j]) < 0) |
||||||
|
continue; |
||||||
|
#endif |
||||||
|
cons_set[cs_idx++] = dev; |
||||||
|
} |
||||||
|
free(console_args); |
||||||
|
free(start); |
||||||
|
/* failed to set any console */ |
||||||
|
if (cs_idx == 0) { |
||||||
|
free(cons_set); |
||||||
|
return 1; |
||||||
|
} else { |
||||||
|
/* Works even if console_devices[console] is NULL. */ |
||||||
|
console_devices[console] = |
||||||
|
(device_t **)realloc(console_devices[console], |
||||||
|
cs_idx * sizeof(device_t *)); |
||||||
|
if (console_devices[console] == NULL) { |
||||||
|
free(cons_set); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
memcpy(console_devices[console], cons_set, cs_idx * |
||||||
|
sizeof(device_t *)); |
||||||
|
|
||||||
|
cd_count[console] = cs_idx; |
||||||
|
} |
||||||
|
free(cons_set); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
#endif /* CONFIG_CONSOLE_MUX */ |
@ -0,0 +1,106 @@ |
|||||||
|
/* |
||||||
|
* (C) Copyright 2008 |
||||||
|
* Gary Jennejohn, DENX Software Engineering GmbH <garyj@denx.de> |
||||||
|
* |
||||||
|
* See file CREDITS for list of people who contributed to this |
||||||
|
* project. |
||||||
|
* |
||||||
|
* This program is free software; you can redistribute it and/or |
||||||
|
* modify it under the terms of the GNU General Public License as |
||||||
|
* published by the Free Software Foundation; either version 2 of |
||||||
|
* the License, or (at your option) any later version. |
||||||
|
* |
||||||
|
* This program is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
* GNU General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program; if not, write to the Free Software |
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||||
|
* MA 02111-1307 USA |
||||||
|
*/ |
||||||
|
|
||||||
|
U-Boot console multiplexing |
||||||
|
=========================== |
||||||
|
|
||||||
|
HOW CONSOLE MULTIPLEXING WORKS |
||||||
|
------------------------------ |
||||||
|
|
||||||
|
This functionality is controlled with CONFIG_CONSOLE_MUX in the board |
||||||
|
configuration file. |
||||||
|
|
||||||
|
Two new files, common/iomux.c and include/iomux.h, contain the heart |
||||||
|
(iomux_doenv()) of the environment setting implementation. |
||||||
|
|
||||||
|
iomux_doenv() is called in common/cmd_nvedit.c to handle setenv and in |
||||||
|
common/console.c in console_init_r() during bootup to initialize |
||||||
|
stdio_devices[]. |
||||||
|
|
||||||
|
A user can use a comma-separated list of devices to set stdin, stdout |
||||||
|
and stderr. For example: "setenv stdin serial,nc". NOTE: No spaces |
||||||
|
are allowed around the comma(s)! |
||||||
|
|
||||||
|
The length of the list is limited by malloc(), since the array used |
||||||
|
is allocated and freed dynamically. |
||||||
|
|
||||||
|
It should be possible to specify any device which console_assign() |
||||||
|
finds acceptable, but the code has only been tested with serial and |
||||||
|
nc. |
||||||
|
|
||||||
|
iomux_doenv() prevents multiple use of the same device, e.g. "setenv |
||||||
|
stdin nc,nc,serial" will discard the second nc. iomux_doenv() is |
||||||
|
not able to modify the environment, however, so that "pri stdin" still |
||||||
|
shows "nc,nc,serial". |
||||||
|
|
||||||
|
The major change in common/console.c was to modify fgetc() to call |
||||||
|
the iomux_tstc() routine in a for-loop. iomux_tstc() in turn calls |
||||||
|
the tstc() routine for every registered device, but exits immediately |
||||||
|
when one of them returns true. fgetc() then calls iomux_getc(), |
||||||
|
which calls the corresponding getc() routine. fgetc() hangs in |
||||||
|
the for-loop until iomux_tstc() returns true and the input can be |
||||||
|
retrieved. |
||||||
|
|
||||||
|
Thus, a user can type into any device registered for stdin. No effort |
||||||
|
has been made to demulitplex simultaneous input from multiple stdin |
||||||
|
devices. |
||||||
|
|
||||||
|
fputc() and fputs() have been modified to call iomux_putc() and |
||||||
|
iomux_puts() respectively, which call the corresponding output |
||||||
|
routines for every registered device. |
||||||
|
|
||||||
|
Thus, a user can see the ouput for any device registered for stdout |
||||||
|
or stderr on all devices registered for stdout or stderr. As an |
||||||
|
example, if stdin=serial,nc and stdout=serial,nc then all output |
||||||
|
for serial, e.g. echos of input on serial, will appear on serial and nc. |
||||||
|
|
||||||
|
Just as with the old console code, this statement is still true: |
||||||
|
If not defined in the environment, the first input device is assigned |
||||||
|
to the 'stdin' file, the first output one to 'stdout' and 'stderr'. |
||||||
|
|
||||||
|
If CONFIG_SYS_CONSOLE_IS_IN_ENV is defined then multiple input/output |
||||||
|
devices can be set at boot time if defined in the environment. |
||||||
|
|
||||||
|
CAVEATS |
||||||
|
------- |
||||||
|
|
||||||
|
Note that common/iomux.c calls console_assign() for every registered |
||||||
|
device as it is discovered. This means that the environment settings |
||||||
|
for application consoles will be set to the last device in the list. |
||||||
|
|
||||||
|
On a slow machine, such as MPC852T clocked at 66MHz, the overhead associated |
||||||
|
with calling tstc() and then getc() means that copy&paste will normally not |
||||||
|
work, even when stdin=stdout=stderr=serial. |
||||||
|
On a faster machine, such as a sequoia, cut&paste of longer (about 80 |
||||||
|
characters) lines works fine when serial is the only device used. |
||||||
|
|
||||||
|
Using nc as a stdin device results in even more overhead because nc_tstc() |
||||||
|
is quite slow. Even on a sequoia cut&paste does not work on the serial |
||||||
|
interface when nc is added to stdin, although there is no character loss using |
||||||
|
the ethernet interface for input. In this test case stdin=serial,nc and |
||||||
|
stdout=serial. |
||||||
|
|
||||||
|
In addition, the overhead associated with sending to two devices, when one of |
||||||
|
them is nc, also causes problems. Even on a sequoia cut&paste does not work |
||||||
|
on the serial interface (stdin=serial) when nc is added to stdout (stdout= |
||||||
|
serial,nc). |
@ -0,0 +1,48 @@ |
|||||||
|
/*
|
||||||
|
* (C) Copyright 2008 |
||||||
|
* Gary Jennejohn, DENX Software Engineering GmbH, garyj@denx.de. |
||||||
|
* |
||||||
|
* See file CREDITS for list of people who contributed to this |
||||||
|
* project. |
||||||
|
* |
||||||
|
* This program is free software; you can redistribute it and/or |
||||||
|
* modify it under the terms of the GNU General Public License as |
||||||
|
* published by the Free Software Foundation; either version 2 of |
||||||
|
* the License, or (at your option) any later version. |
||||||
|
* |
||||||
|
*This program is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
* GNU General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program; if not, write to the Free Software |
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||||
|
* MA 02111-1307 USA |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef _IO_MUX_H |
||||||
|
#define _IO_MUX_H |
||||||
|
|
||||||
|
#include <devices.h> |
||||||
|
|
||||||
|
/*
|
||||||
|
* Stuff required to support console multiplexing. |
||||||
|
*/ |
||||||
|
|
||||||
|
/*
|
||||||
|
* Pointers to devices used for each file type. Defined in console.c |
||||||
|
* but storage is allocated in iomux.c. |
||||||
|
*/ |
||||||
|
extern device_t **console_devices[MAX_FILES]; |
||||||
|
/*
|
||||||
|
* The count of devices assigned to each FILE. Defined in console.c |
||||||
|
* and populated in iomux.c. |
||||||
|
*/ |
||||||
|
extern int cd_count[MAX_FILES]; |
||||||
|
|
||||||
|
int iomux_doenv(const int, const char *); |
||||||
|
void iomux_printdevs(const int); |
||||||
|
device_t *search_device(int, char *); |
||||||
|
|
||||||
|
#endif /* _IO_MUX_H */ |
Loading…
Reference in new issue