116a28ef2SGary Jennejohn /* 216a28ef2SGary Jennejohn * (C) Copyright 2008 316a28ef2SGary Jennejohn * Gary Jennejohn, DENX Software Engineering GmbH, garyj@denx.de. 416a28ef2SGary Jennejohn * 516a28ef2SGary Jennejohn * See file CREDITS for list of people who contributed to this 616a28ef2SGary Jennejohn * project. 716a28ef2SGary Jennejohn * 816a28ef2SGary Jennejohn * This program is free software; you can redistribute it and/or 916a28ef2SGary Jennejohn * modify it under the terms of the GNU General Public License as 1016a28ef2SGary Jennejohn * published by the Free Software Foundation; either version 2 of 1116a28ef2SGary Jennejohn * the License, or (at your option) any later version. 1216a28ef2SGary Jennejohn * 1316a28ef2SGary Jennejohn * This program is distributed in the hope that it will be useful, 1416a28ef2SGary Jennejohn * but WITHOUT ANY WARRANTY; without even the implied warranty of 1516a28ef2SGary Jennejohn * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1616a28ef2SGary Jennejohn * GNU General Public License for more details. 1716a28ef2SGary Jennejohn * 1816a28ef2SGary Jennejohn * You should have received a copy of the GNU General Public License 1916a28ef2SGary Jennejohn * along with this program; if not, write to the Free Software 2016a28ef2SGary Jennejohn * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 2116a28ef2SGary Jennejohn * MA 02111-1307 USA 2216a28ef2SGary Jennejohn */ 2316a28ef2SGary Jennejohn 2416a28ef2SGary Jennejohn #include <common.h> 2516a28ef2SGary Jennejohn #include <serial.h> 2616a28ef2SGary Jennejohn #include <malloc.h> 2716a28ef2SGary Jennejohn 2816a28ef2SGary Jennejohn #ifdef CONFIG_CONSOLE_MUX 2916a28ef2SGary Jennejohn void iomux_printdevs(const int console) 3016a28ef2SGary Jennejohn { 3116a28ef2SGary Jennejohn int i; 32*52cb4d4fSJean-Christophe PLAGNIOL-VILLARD struct stdio_dev *dev; 3316a28ef2SGary Jennejohn 3416a28ef2SGary Jennejohn for (i = 0; i < cd_count[console]; i++) { 3516a28ef2SGary Jennejohn dev = console_devices[console][i]; 3616a28ef2SGary Jennejohn printf("%s ", dev->name); 3716a28ef2SGary Jennejohn } 3816a28ef2SGary Jennejohn printf("\n"); 3916a28ef2SGary Jennejohn } 4016a28ef2SGary Jennejohn 4116a28ef2SGary Jennejohn /* This tries to preserve the old list if an error occurs. */ 4216a28ef2SGary Jennejohn int iomux_doenv(const int console, const char *arg) 4316a28ef2SGary Jennejohn { 4416a28ef2SGary Jennejohn char *console_args, *temp, **start; 4516a28ef2SGary Jennejohn int i, j, k, io_flag, cs_idx, repeat; 46*52cb4d4fSJean-Christophe PLAGNIOL-VILLARD struct stdio_dev *dev; 47*52cb4d4fSJean-Christophe PLAGNIOL-VILLARD struct stdio_dev **cons_set; 4816a28ef2SGary Jennejohn 4916a28ef2SGary Jennejohn console_args = strdup(arg); 5016a28ef2SGary Jennejohn if (console_args == NULL) 5116a28ef2SGary Jennejohn return 1; 5216a28ef2SGary Jennejohn /* 5316a28ef2SGary Jennejohn * Check whether a comma separated list of devices was 5416a28ef2SGary Jennejohn * entered and count how many devices were entered. 5516a28ef2SGary Jennejohn * The array start[] has pointers to the beginning of 5616a28ef2SGary Jennejohn * each device name (up to MAX_CONSARGS devices). 5716a28ef2SGary Jennejohn * 5816a28ef2SGary Jennejohn * Have to do this twice - once to count the number of 5916a28ef2SGary Jennejohn * commas and then again to populate start. 6016a28ef2SGary Jennejohn */ 6116a28ef2SGary Jennejohn i = 0; 6216a28ef2SGary Jennejohn temp = console_args; 6316a28ef2SGary Jennejohn for (;;) { 6416a28ef2SGary Jennejohn temp = strchr(temp, ','); 6516a28ef2SGary Jennejohn if (temp != NULL) { 6616a28ef2SGary Jennejohn i++; 6716a28ef2SGary Jennejohn temp++; 6816a28ef2SGary Jennejohn continue; 6916a28ef2SGary Jennejohn } 7016a28ef2SGary Jennejohn /* There's always one entry more than the number of commas. */ 7116a28ef2SGary Jennejohn i++; 7216a28ef2SGary Jennejohn break; 7316a28ef2SGary Jennejohn } 7416a28ef2SGary Jennejohn start = (char **)malloc(i * sizeof(char *)); 7516a28ef2SGary Jennejohn if (start == NULL) { 7616a28ef2SGary Jennejohn free(console_args); 7716a28ef2SGary Jennejohn return 1; 7816a28ef2SGary Jennejohn } 7916a28ef2SGary Jennejohn i = 0; 8016a28ef2SGary Jennejohn start[0] = console_args; 8116a28ef2SGary Jennejohn for (;;) { 8216a28ef2SGary Jennejohn temp = strchr(start[i++], ','); 8316a28ef2SGary Jennejohn if (temp == NULL) 8416a28ef2SGary Jennejohn break; 8516a28ef2SGary Jennejohn *temp = '\0'; 8616a28ef2SGary Jennejohn start[i] = temp + 1; 8716a28ef2SGary Jennejohn } 88*52cb4d4fSJean-Christophe PLAGNIOL-VILLARD cons_set = (struct stdio_dev **)calloc(i, sizeof(struct stdio_dev *)); 8916a28ef2SGary Jennejohn if (cons_set == NULL) { 9016a28ef2SGary Jennejohn free(start); 9116a28ef2SGary Jennejohn free(console_args); 9216a28ef2SGary Jennejohn return 1; 9316a28ef2SGary Jennejohn } 9416a28ef2SGary Jennejohn 9516a28ef2SGary Jennejohn switch (console) { 9616a28ef2SGary Jennejohn case stdin: 9716a28ef2SGary Jennejohn io_flag = DEV_FLAGS_INPUT; 9816a28ef2SGary Jennejohn break; 9916a28ef2SGary Jennejohn case stdout: 10016a28ef2SGary Jennejohn case stderr: 10116a28ef2SGary Jennejohn io_flag = DEV_FLAGS_OUTPUT; 10216a28ef2SGary Jennejohn break; 10316a28ef2SGary Jennejohn default: 10416a28ef2SGary Jennejohn free(start); 10516a28ef2SGary Jennejohn free(console_args); 10616a28ef2SGary Jennejohn free(cons_set); 10716a28ef2SGary Jennejohn return 1; 10816a28ef2SGary Jennejohn } 10916a28ef2SGary Jennejohn 11016a28ef2SGary Jennejohn cs_idx = 0; 11116a28ef2SGary Jennejohn for (j = 0; j < i; j++) { 11216a28ef2SGary Jennejohn /* 11316a28ef2SGary Jennejohn * Check whether the device exists and is valid. 11416a28ef2SGary Jennejohn * console_assign() also calls search_device(), 11516a28ef2SGary Jennejohn * but I need the pointer to the device. 11616a28ef2SGary Jennejohn */ 11716a28ef2SGary Jennejohn dev = search_device(io_flag, start[j]); 11816a28ef2SGary Jennejohn if (dev == NULL) 11916a28ef2SGary Jennejohn continue; 12016a28ef2SGary Jennejohn /* 12116a28ef2SGary Jennejohn * Prevent multiple entries for a device. 12216a28ef2SGary Jennejohn */ 12316a28ef2SGary Jennejohn repeat = 0; 12416a28ef2SGary Jennejohn for (k = 0; k < cs_idx; k++) { 12516a28ef2SGary Jennejohn if (dev == cons_set[k]) { 12616a28ef2SGary Jennejohn repeat++; 12716a28ef2SGary Jennejohn break; 12816a28ef2SGary Jennejohn } 12916a28ef2SGary Jennejohn } 13016a28ef2SGary Jennejohn if (repeat) 13116a28ef2SGary Jennejohn continue; 13216a28ef2SGary Jennejohn /* 13316a28ef2SGary Jennejohn * Try assigning the specified device. 13416a28ef2SGary Jennejohn * This could screw up the console settings for apps. 13516a28ef2SGary Jennejohn */ 13616a28ef2SGary Jennejohn if (console_assign(console, start[j]) < 0) 13716a28ef2SGary Jennejohn continue; 13816a28ef2SGary Jennejohn #ifdef CONFIG_SERIAL_MULTI 13916a28ef2SGary Jennejohn /* 14016a28ef2SGary Jennejohn * This was taken from common/cmd_nvedit.c. 14116a28ef2SGary Jennejohn * This will never work because serial_assign() returns 14216a28ef2SGary Jennejohn * 1 upon error, not -1. 14316a28ef2SGary Jennejohn * This would almost always return an error anyway because 14416a28ef2SGary Jennejohn * serial_assign() expects the name of a serial device, like 14516a28ef2SGary Jennejohn * serial_smc, but the user generally only wants to set serial. 14616a28ef2SGary Jennejohn */ 14716a28ef2SGary Jennejohn if (serial_assign(start[j]) < 0) 14816a28ef2SGary Jennejohn continue; 14916a28ef2SGary Jennejohn #endif 15016a28ef2SGary Jennejohn cons_set[cs_idx++] = dev; 15116a28ef2SGary Jennejohn } 15216a28ef2SGary Jennejohn free(console_args); 15316a28ef2SGary Jennejohn free(start); 15416a28ef2SGary Jennejohn /* failed to set any console */ 15516a28ef2SGary Jennejohn if (cs_idx == 0) { 15616a28ef2SGary Jennejohn free(cons_set); 15716a28ef2SGary Jennejohn return 1; 15816a28ef2SGary Jennejohn } else { 15916a28ef2SGary Jennejohn /* Works even if console_devices[console] is NULL. */ 16016a28ef2SGary Jennejohn console_devices[console] = 161*52cb4d4fSJean-Christophe PLAGNIOL-VILLARD (struct stdio_dev **)realloc(console_devices[console], 162*52cb4d4fSJean-Christophe PLAGNIOL-VILLARD cs_idx * sizeof(struct stdio_dev *)); 16316a28ef2SGary Jennejohn if (console_devices[console] == NULL) { 16416a28ef2SGary Jennejohn free(cons_set); 16516a28ef2SGary Jennejohn return 1; 16616a28ef2SGary Jennejohn } 16716a28ef2SGary Jennejohn memcpy(console_devices[console], cons_set, cs_idx * 168*52cb4d4fSJean-Christophe PLAGNIOL-VILLARD sizeof(struct stdio_dev *)); 16916a28ef2SGary Jennejohn 17016a28ef2SGary Jennejohn cd_count[console] = cs_idx; 17116a28ef2SGary Jennejohn } 17216a28ef2SGary Jennejohn free(cons_set); 17316a28ef2SGary Jennejohn return 0; 17416a28ef2SGary Jennejohn } 17516a28ef2SGary Jennejohn #endif /* CONFIG_CONSOLE_MUX */ 176