ldlinux: Fix serial output and delete eprintf()
[syslinux.git] / core / conio.c
blob3b8a103bb4544cb91a5364ee47c98cdf3c7c1d86
1 /*
2 * -----------------------------------------------------------------------
4 * Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
5 * Copyright 2009 Intel Corporation; author: H. Peter Anvin
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
10 * Boston MA 02111-1307, USA; either version 2 of the License, or
11 * (at your option) any later version; incorporated herein by reference.
13 * -----------------------------------------------------------------------
16 * conio.c
18 * Console I/O code, except:
19 * writechr, writestr_early - module-dependent
20 * writestr, crlf - writestr.inc
21 * writehex* - writehex.inc
23 #include <sys/io.h>
24 #include <stddef.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <fs.h>
28 #include <com32.h>
29 #include <sys/cpu.h>
31 #include "bios.h"
32 #include "graphics.h"
34 union screen _cursor;
35 union screen _screensize;
38 * Serial console stuff.
40 __export uint16_t SerialPort = 0; /* Serial port base (or 0 for no serial port) */
41 __export uint8_t FlowInput = 0; /* Input bits for serial flow */
42 __export uint16_t BaudDivisor = 115200/9600; /* Baud rate divisor */
43 __export uint8_t FlowIgnore = 0; /* Ignore input unless these bits set */
44 __export uint16_t DisplayCon = 0x01; /* Display console enabled */
45 __export uint8_t FlowOutput = 0; /* Output to assert for serial flow */
47 __export uint8_t DisplayMask = 0x07; /* Display modes mask */
49 uint8_t ScrollAttribute = 0x07; /* Grey on white (normal text color) */
52 * loadkeys: Load a LILO-style keymap
54 * Returns 0 on success, or -1 on error.
56 __export int loadkeys(char *filename)
58 FILE *f;
60 f = fopen(filename, "r");
61 if (!f)
62 return -1;
64 fread(KbdMap, 1, sizeof(KbdMap), f);
66 fclose(f);
67 return 0;
71 * write_serial: If serial output is enabled, write character on
72 * serial port.
74 __export void write_serial(char data)
76 if (!SerialPort)
77 return;
79 if (!(DisplayMask & 0x04))
80 return;
82 while (1) {
83 char ch;
85 ch = inb(SerialPort + 5); /* LSR */
87 /* Wait for space in transmit register */
88 if (!(ch & 0x20))
89 continue;
91 /* Wait for input flow control */
92 ch = inb(SerialPort + 6);
93 ch &= FlowInput;
94 if (ch != FlowInput)
95 continue;
97 break;
100 outb(data, SerialPort); /* Send data */
101 io_delay();
104 void pm_write_serial(com32sys_t *regs)
106 write_serial(regs->eax.b[0]);
109 void pm_serialcfg(com32sys_t *regs)
111 uint8_t al, ah;
113 regs->eax.w[0] = SerialPort;
114 regs->ecx.w[0] = BaudDivisor;
116 al = FlowOutput;
117 ah = FlowInput;
119 al |= ah;
120 ah = FlowIgnore;
121 ah >>= 4;
123 if (!DisplayCon)
124 ah |= 0x80;
126 regs->ebx.w[0] = al | (ah << 8);
130 * write_serial_str: write_serial for strings
132 __export void write_serial_str(char *data)
134 char ch;
136 while ((ch = *data++))
137 write_serial(ch);
141 * pollchar: check if we have an input character pending
143 * Returns 1 if character pending.
145 __export int pollchar(void)
147 com32sys_t ireg, oreg;
148 uint8_t data = 0;
150 memset(&ireg, 0, sizeof(ireg));
152 ireg.eax.b[1] = 0x11; /* Poll keyboard */
153 __intcall(0x16, &ireg, &oreg);
155 if (!(oreg.eflags.l & EFLAGS_ZF))
156 return 1;
158 if (SerialPort) {
159 cli();
161 /* Already-queued input? */
162 if (SerialTail == SerialHead) {
163 /* LSR */
164 data = !(inb(SerialPort + 5) & 1);
165 if (!data) {
166 /* MSR */
167 data = inb(SerialPort + 6);
169 /* Required status bits */
170 data &= FlowIgnore;
172 if (data == FlowIgnore)
173 data = 1;
174 else
175 data = 0;
176 } else
177 data = 1;
178 } else
179 data = 1;
180 sti();
183 return data;
186 void pm_pollchar(com32sys_t *regs)
188 if (pollchar())
189 regs->eflags.l &= ~EFLAGS_ZF;
190 else
191 regs->eflags.l |= EFLAGS_ZF;
194 extern void do_idle(void);
197 * getchar: Read a character from keyboard or serial port
199 __export char getchar(char *hi)
201 com32sys_t ireg, oreg;
202 unsigned char data;
204 memset(&ireg, 0, sizeof(ireg));
205 memset(&oreg, 0, sizeof(oreg));
206 while (1) {
207 call16(do_idle, &zero_regs, NULL);
209 ireg.eax.b[1] = 0x11; /* Poll keyboard */
210 __intcall(0x16, &ireg, &oreg);
212 if (oreg.eflags.l & EFLAGS_ZF) {
213 if (!SerialPort)
214 continue;
216 cli();
217 if (SerialTail != SerialHead) {
218 /* serial queued */
219 sti(); /* We already know we'll consume data */
220 data = *SerialTail++;
222 if (SerialTail > SerialHead + serial_buf_size)
223 SerialTail = SerialHead;
224 } else {
225 /* LSR */
226 data = inb(SerialPort + 5) & 1;
227 if (!data) {
228 sti();
229 continue;
231 data = inb(SerialPort + 6);
232 data &= FlowIgnore;
233 if (data != FlowIgnore) {
234 sti();
235 continue;
238 data = inb(SerialPort);
239 sti();
240 break;
242 } else {
243 /* Keyboard input? */
244 ireg.eax.b[1] = 0x10; /* Get keyboard input */
245 __intcall(0x16, &ireg, &oreg);
247 data = oreg.eax.b[0];
248 *hi = oreg.eax.b[1];
250 if (data == 0xE0)
251 data = 0;
253 if (data) {
254 /* Convert character sets */
255 data = KbdMap[data];
259 break;
262 reset_idle(); /* Character received */
263 return data;
266 void pm_getchar(com32sys_t *regs)
268 regs->eax.b[0] = getchar((char *)&regs->eax.b[1]);