Home | History | Annotate | Line # | Download | only in zboot
      1 /*	$NetBSD: unixcons.c,v 1.3 2014/03/26 08:02:38 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2009 NONAKA Kimihiro <nonaka (at) netbsd.org>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #include "boot.h"
     29 #include "bootinfo.h"
     30 #include "unixdev.h"
     31 
     32 #include "compat_linux.h"
     33 #include "termios.h"
     34 
     35 struct btinfo_console bi_cons;
     36 
     37 static int iodev = CONSDEV_GLASS;
     38 static int infd = 0;
     39 static int outfd = 1;
     40 
     41 static const char *comdevname[] = {
     42 	"/dev/ttyS0",
     43 };
     44 
     45 static void common_putc(int fd, int c);
     46 static int common_getc(int fd, int timo);
     47 
     48 void
     49 consinit(int dev, int speed)
     50 {
     51 	struct linux_termios termios;
     52 	int fd;
     53 
     54 	switch (dev) {
     55 	case CONSDEV_COM0:
     56 		iodev = dev;
     57 		break;
     58 
     59 	case CONSDEV_GLASS:
     60 	default:
     61  glass_console:
     62 		iodev = CONSDEV_GLASS;
     63 		break;
     64 	}
     65 
     66 	if (infd >= 0 && infd == outfd) {
     67 		uclose(infd);
     68 		infd = 0;
     69 		outfd = 1;
     70 	}
     71 
     72 	if (iodev == CONSDEV_GLASS) {
     73 		infd = 0;
     74 		outfd = 1;
     75 
     76 		strlcpy(bi_cons.devname, "glass", sizeof(bi_cons.devname));
     77 		bi_cons.addr = -1;
     78 		bi_cons.speed = -1;
     79 	} else {
     80 		fd = uopen(comdevname[iodev - CONSDEV_COM0], LINUX_O_RDWR);
     81 		if (fd < 0)
     82 			goto glass_console;
     83 		infd = outfd = fd;
     84 
     85 		/* set speed */
     86 		linux_tcgetattr(fd, &termios);
     87 		if (linux_cfsetspeed(&termios, speed) < 0) {
     88 			speed = 9600;
     89 			if (linux_cfsetspeed(&termios, speed) < 0)
     90 				goto glass_console;
     91 		}
     92 		if (linux_tcsetattr(fd, LINUX_TCSETS, &termios) < 0)
     93 			goto glass_console;
     94 
     95 		snprintf(bi_cons.devname, sizeof(bi_cons.devname), "com%d",
     96 		    iodev - CONSDEV_COM0);
     97 		bi_cons.addr = -1;
     98 		bi_cons.speed = speed;
     99 	}
    100 	BI_ADD(&bi_cons, BTINFO_CONSDEV, sizeof(bi_cons));
    101 }
    102 
    103 void
    104 putchar(int c)
    105 {
    106 
    107 	common_putc(outfd, c);
    108 }
    109 
    110 int
    111 getchar(void)
    112 {
    113 
    114 	return common_getc(infd, 1);
    115 }
    116 
    117 static void
    118 common_putc(int fd, int c)
    119 {
    120 
    121 	(void)uwrite(fd, &c, 1);
    122 }
    123 
    124 static int
    125 common_getc(int fd, int timo)
    126 {
    127 	struct linux_timeval tv;
    128 	fd_set fdset;
    129 	int nfds, n;
    130 	char c;
    131 
    132 	for (; timo < 0 || timo > 0; --timo) {
    133 		tv.tv_sec = 1;
    134 		tv.tv_usec = 0;
    135 		FD_ZERO(&fdset);
    136 
    137 		nfds = 1;
    138 		FD_SET(fd, &fdset);
    139 
    140 		n = uselect(nfds, &fdset, NULL, NULL, &tv);
    141 		if (n > 0)
    142 			break;
    143 	}
    144 
    145 	if (timo > 0) {
    146 		for (fd = 0; fd < nfds; fd++) {
    147 			if (FD_ISSET(fd, &fdset)) {
    148 				return (uread(fd, &c, 1) < 1 ? -1 : c);
    149 			}
    150 		}
    151 	}
    152 	return -1;
    153 }
    154 
    155 int
    156 awaitkey(int timeout, int tell)
    157 {
    158 	struct linux_termios orig_termios, raw_termios;
    159 	int c = 0;
    160 	int i;
    161 
    162 	/* set raw mode */
    163 	linux_tcgetattr(infd, &orig_termios);
    164 	raw_termios = orig_termios;
    165 	linux_cfmakeraw(&raw_termios);
    166 	linux_tcsetattr(infd, LINUX_TCSETS, &raw_termios);
    167 
    168 	for (i = timeout; i > 0; i--) {
    169 		if (tell) {
    170 			char numbuf[20];
    171 			int len, j;
    172 
    173 			len = snprintf(numbuf, sizeof(numbuf), "%d ", i);
    174 			for (j = 0; j < len; j++)
    175 				numbuf[len + j] = '\b';
    176 			numbuf[len + j] = '\0';
    177 			printf("%s", numbuf);
    178 		}
    179 		c = common_getc(infd, 1);
    180 		if (c == 0)
    181 			c = -1;
    182 		if (c >= 0)
    183 			break;
    184 	}
    185 	if (i == 0)
    186 		c = '\0';
    187 
    188 	/* set original mode */
    189 	linux_tcsetattr(infd, LINUX_TCSETS, &orig_termios);
    190 
    191 	if (tell)
    192 		printf("0 \n");
    193 
    194 	return c;
    195 }
    196 
    197 void dummycall2(void);
    198 void
    199 dummycall2(void)
    200 {
    201 
    202 	(void)linux_termio_to_bsd_termios;
    203 	(void)bsd_termios_to_linux_termio;
    204 	(void)linux_termios_to_bsd_termios;
    205 	(void)bsd_termios_to_linux_termios;
    206 }
    207