Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Generic serial console support
0003  *
0004  * Author: Mark A. Greer <mgreer@mvista.com>
0005  *
0006  * Code in serial_edit_cmdline() copied from <file:arch/ppc/boot/simple/misc.c>
0007  * and was written by Matt Porter <mporter@kernel.crashing.org>.
0008  *
0009  * 2001,2006 (c) MontaVista Software, Inc.  This file is licensed under
0010  * the terms of the GNU General Public License version 2.  This program
0011  * is licensed "as is" without any warranty of any kind, whether express
0012  * or implied.
0013  */
0014 #include <stdarg.h>
0015 #include <stddef.h>
0016 #include "types.h"
0017 #include "string.h"
0018 #include "stdio.h"
0019 #include "io.h"
0020 #include "ops.h"
0021 
0022 static int serial_open(void)
0023 {
0024     struct serial_console_data *scdp = console_ops.data;
0025     return scdp->open();
0026 }
0027 
0028 static void serial_write(const char *buf, int len)
0029 {
0030     struct serial_console_data *scdp = console_ops.data;
0031 
0032     while (*buf != '\0')
0033         scdp->putc(*buf++);
0034 }
0035 
0036 static void serial_edit_cmdline(char *buf, int len, unsigned int timeout)
0037 {
0038     int timer = 0, count;
0039     char ch, *cp;
0040     struct serial_console_data *scdp = console_ops.data;
0041 
0042     cp = buf;
0043     count = strlen(buf);
0044     cp = &buf[count];
0045     count++;
0046 
0047     do {
0048         if (scdp->tstc()) {
0049             while (((ch = scdp->getc()) != '\n') && (ch != '\r')) {
0050                 /* Test for backspace/delete */
0051                 if ((ch == '\b') || (ch == '\177')) {
0052                     if (cp != buf) {
0053                         cp--;
0054                         count--;
0055                         printf("\b \b");
0056                     }
0057                 /* Test for ^x/^u (and wipe the line) */
0058                 } else if ((ch == '\030') || (ch == '\025')) {
0059                     while (cp != buf) {
0060                         cp--;
0061                         count--;
0062                         printf("\b \b");
0063                     }
0064                 } else if (count < len) {
0065                         *cp++ = ch;
0066                         count++;
0067                         scdp->putc(ch);
0068                 }
0069             }
0070             break;  /* Exit 'timer' loop */
0071         }
0072         udelay(1000);  /* 1 msec */
0073     } while (timer++ < timeout);
0074     *cp = 0;
0075 }
0076 
0077 static void serial_close(void)
0078 {
0079     struct serial_console_data *scdp = console_ops.data;
0080 
0081     if (scdp->close)
0082         scdp->close();
0083 }
0084 
0085 static void *serial_get_stdout_devp(void)
0086 {
0087     void *devp;
0088     char devtype[MAX_PROP_LEN];
0089     char path[MAX_PATH_LEN];
0090 
0091     devp = finddevice("/chosen");
0092     if (devp == NULL)
0093         goto err_out;
0094 
0095     if (getprop(devp, "linux,stdout-path", path, MAX_PATH_LEN) > 0 ||
0096         getprop(devp, "stdout-path", path, MAX_PATH_LEN) > 0) {
0097         devp = finddevice(path);
0098         if (devp == NULL)
0099             goto err_out;
0100 
0101         if ((getprop(devp, "device_type", devtype, sizeof(devtype)) > 0)
0102                 && !strcmp(devtype, "serial"))
0103             return devp;
0104     }
0105 err_out:
0106     return NULL;
0107 }
0108 
0109 static struct serial_console_data serial_cd;
0110 
0111 /* Node's "compatible" property determines which serial driver to use */
0112 int serial_console_init(void)
0113 {
0114     void *devp;
0115     int rc = -1;
0116 
0117     devp = serial_get_stdout_devp();
0118     if (devp == NULL)
0119         goto err_out;
0120 
0121     if (dt_is_compatible(devp, "ns16550") ||
0122         dt_is_compatible(devp, "pnpPNP,501"))
0123         rc = ns16550_console_init(devp, &serial_cd);
0124 #ifdef CONFIG_CPM
0125     else if (dt_is_compatible(devp, "fsl,cpm1-scc-uart") ||
0126              dt_is_compatible(devp, "fsl,cpm1-smc-uart") ||
0127              dt_is_compatible(devp, "fsl,cpm2-scc-uart") ||
0128              dt_is_compatible(devp, "fsl,cpm2-smc-uart"))
0129         rc = cpm_console_init(devp, &serial_cd);
0130 #endif
0131 #ifdef CONFIG_PPC_MPC52xx
0132     else if (dt_is_compatible(devp, "fsl,mpc5200-psc-uart"))
0133         rc = mpc5200_psc_console_init(devp, &serial_cd);
0134 #endif
0135 #ifdef CONFIG_PPC_POWERNV
0136     else if (dt_is_compatible(devp, "ibm,opal-console-raw"))
0137         rc = opal_console_init(devp, &serial_cd);
0138 #endif
0139 
0140     /* Add other serial console driver calls here */
0141 
0142     if (!rc) {
0143         console_ops.open = serial_open;
0144         console_ops.write = serial_write;
0145         console_ops.close = serial_close;
0146         console_ops.data = &serial_cd;
0147 
0148         if (serial_cd.getc)
0149             console_ops.edit_cmdline = serial_edit_cmdline;
0150 
0151         return 0;
0152     }
0153 err_out:
0154     return -1;
0155 }