xfs: Remove unnecessary free()'s
[syslinux.git] / core / conio.c
blobabfceb881cfb6fd11eb441d98c8c818632a35c8c
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 uint8_t ScrollAttribute = 0x07; /* Grey on white (normal text color) */
50 * loadkeys: Load a LILO-style keymap
52 * Returns 0 on success, or -1 on error.
54 __export int loadkeys(char *filename)
56 FILE *f;
58 f = fopen(filename, "r");
59 if (!f)
60 return -1;
62 fread(KbdMap, 1, sizeof(KbdMap), f);
64 fclose(f);
65 return 0;
69 * write_serial: If serial output is enabled, write character on
70 * serial port.
72 __export void write_serial(char data)
74 if (!SerialPort)
75 return;
77 while (1) {
78 char ch;
80 ch = inb(SerialPort + 5); /* LSR */
82 /* Wait for space in transmit register */
83 if (!(ch & 0x20))
84 continue;
86 /* Wait for input flow control */
87 ch = inb(SerialPort + 6);
88 ch &= FlowInput;
89 if (ch != FlowInput)
90 continue;
92 break;
95 outb(data, SerialPort); /* Send data */
96 io_delay();
99 void pm_write_serial(com32sys_t *regs)
101 write_serial(regs->eax.b[0]);
104 void pm_serialcfg(com32sys_t *regs)
106 uint8_t al, ah;
108 regs->eax.w[0] = SerialPort;
109 regs->ecx.w[0] = BaudDivisor;
111 al = FlowOutput;
112 ah = FlowInput;
114 al |= ah;
115 ah = FlowIgnore;
116 ah >>= 4;
118 if (!DisplayCon)
119 ah |= 0x80;
121 regs->ebx.w[0] = al | (ah << 8);
125 * write_serial_str: write_serial for strings
127 __export void write_serial_str(char *data)
129 char ch;
131 while ((ch = *data++))
132 write_serial(ch);
136 * pollchar: check if we have an input character pending
138 * Returns 1 if character pending.
140 __export int pollchar(void)
142 com32sys_t ireg, oreg;
143 uint8_t data = 0;
145 memset(&ireg, 0, sizeof(ireg));
147 ireg.eax.b[1] = 0x11; /* Poll keyboard */
148 __intcall(0x16, &ireg, &oreg);
150 if (!(oreg.eflags.l & EFLAGS_ZF))
151 return 1;
153 if (SerialPort) {
154 cli();
156 /* Already-queued input? */
157 if (SerialTail == SerialHead) {
158 /* LSR */
159 data = inb(SerialPort + 5) & 1;
160 if (data) {
161 /* MSR */
162 data = inb(SerialPort + 6);
164 /* Required status bits */
165 if (data) {
166 data &= FlowIgnore;
167 if (data != FlowIgnore)
168 data = 0;
169 else
170 data = 1;
174 sti();
177 return data;
180 void pm_pollchar(com32sys_t *regs)
182 if (pollchar())
183 regs->eflags.l &= ~EFLAGS_ZF;
184 else
185 regs->eflags.l |= EFLAGS_ZF;
188 extern void do_idle(void);
191 * getchar: Read a character from keyboard or serial port
193 __export char getchar(char *hi)
195 com32sys_t ireg, oreg;
196 unsigned char data;
198 memset(&ireg, 0, sizeof(ireg));
199 memset(&oreg, 0, sizeof(oreg));
200 while (1) {
201 call16(do_idle, &zero_regs, NULL);
203 ireg.eax.b[1] = 0x11; /* Poll keyboard */
204 __intcall(0x16, &ireg, &oreg);
206 if (oreg.eflags.l & EFLAGS_ZF) {
207 if (!SerialPort)
208 continue;
210 cli();
211 if (SerialTail != SerialHead) {
212 /* serial queued */
213 sti(); /* We already know we'll consume data */
214 data = *SerialTail++;
216 SerialTail = (char *)((unsigned long)SerialTail & (serial_buf_size - 1));
217 } else {
218 /* LSR */
219 data = inb(SerialPort + 5) & 1;
220 if (!data) {
221 sti();
222 continue;
224 data = inb(SerialPort + 6);
225 data &= FlowIgnore;
226 if (data != FlowIgnore) {
227 sti();
228 continue;
231 data = inb(SerialPort);
232 sti();
233 break;
235 } else {
236 /* Keyboard input? */
237 ireg.eax.b[1] = 0x10; /* Get keyboard input */
238 __intcall(0x16, &ireg, &oreg);
240 data = oreg.eax.b[0];
241 *hi = oreg.eax.b[1];
243 if (data == 0xE0)
244 data = 0;
246 if (data) {
247 /* Convert character sets */
248 data = KbdMap[data];
252 break;
255 reset_idle(); /* Character received */
256 return data;
259 void pm_getchar(com32sys_t *regs)
261 regs->eax.b[0] = getchar((char *)&regs->eax.b[1]);