diff options
author | Gary Jennejohn <garyj@denx.de> | 2008-11-06 15:04:23 +0100 |
---|---|---|
committer | Wolfgang Denk <wd@denx.de> | 2008-12-07 01:23:35 +0100 |
commit | 16a28ef219c27423a1ef502f19070c4d375079b8 (patch) | |
tree | 2241bdb2293824bdb7b82e1ff8d54e9246c81bcc /common/iomux.c | |
parent | 774ce72026f74ac9641bcbbc588b20f2e13f7ab8 (diff) |
IOMUX: Add console multiplexing support.
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>
Diffstat (limited to 'common/iomux.c')
-rw-r--r-- | common/iomux.c | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/common/iomux.c b/common/iomux.c new file mode 100644 index 0000000000..bdcc853ff0 --- /dev/null +++ b/common/iomux.c @@ -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 */ |