source: bootcd/isolinux/syslinux-6.03/core/conio.c @ dd1be7c

Last change on this file since dd1be7c was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 5.9 KB
Line 
1/*
2 * -----------------------------------------------------------------------
3 *
4 *   Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
5 *   Copyright 2009-2014 Intel Corporation; author: H. Peter Anvin
6 *
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.
12 *
13 * -----------------------------------------------------------------------
14 *
15 *
16 * conio.c
17 *
18 * Console I/O code, except:
19 *   writechr, writestr_early   - module-dependent
20 *   writestr, crlf             - writestr.inc
21 *   writehex*                  - writehex.inc
22 */
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>
30#include <syslinux/firmware.h>
31
32#include "bios.h"
33#include "graphics.h"
34
35union screen _cursor;
36union screen _screensize;
37
38/*
39 * Serial console stuff.
40 */
41__export uint16_t SerialPort = 0;   /* Serial port base (or 0 for no serial port) */
42__export uint8_t FlowInput = 0;     /* Input bits for serial flow */
43__export uint16_t BaudDivisor = 115200/9600; /* Baud rate divisor */
44__export uint8_t FlowIgnore = 0;    /* Ignore input unless these bits set */
45__export uint16_t DisplayCon = 0x01;    /* Display console enabled */
46__export uint8_t FlowOutput = 0;        /* Output to assert for serial flow */
47
48__export uint8_t DisplayMask = 0x07;    /* Display modes mask */
49
50uint8_t ScrollAttribute = 0x07; /* Grey on white (normal text color) */
51
52/*
53 * loadkeys:    Load a LILO-style keymap
54 *
55 * Returns 0 on success, or -1 on error.
56 */
57__export int loadkeys(const char *filename)
58{
59        FILE *f;
60
61        f = fopen(filename, "r");
62        if (!f)
63                return -1;
64
65        fread(KbdMap, 1, sizeof(KbdMap), f);
66
67        fclose(f);
68        return 0;
69}
70
71/*
72 * write_serial: If serial output is enabled, write character on
73 * serial port.
74 */
75__export void write_serial(char data)
76{
77        if (!SerialPort)
78                return;
79
80        if (!(DisplayMask & 0x04))
81                return;
82
83        while (1) {
84                char ch;
85
86                ch = inb(SerialPort + 5); /* LSR */
87
88                /* Wait for space in transmit register */
89                if (!(ch & 0x20))
90                        continue;
91
92                /* Wait for input flow control */
93                ch = inb(SerialPort + 6);
94                ch &= FlowInput;
95                if (ch != FlowInput)
96                        continue;
97
98                break;
99        }
100
101        outb(data, SerialPort); /* Send data */
102        io_delay();
103}
104
105void pm_write_serial(com32sys_t *regs)
106{
107        write_serial(regs->eax.b[0]);
108}
109
110void serialcfg(uint16_t *iobase, uint16_t *divisor, uint16_t *flowctl)
111{
112        uint8_t al, ah;
113
114        *iobase = SerialPort;
115        *divisor = BaudDivisor;
116
117        al = FlowOutput;
118        ah = FlowInput;
119
120        al |= ah;
121        ah = FlowIgnore;
122        ah >>= 4;
123
124        if (!DisplayCon)
125                ah |= 0x80;
126
127        *flowctl = al | (ah << 8);
128}
129
130void pm_serialcfg(com32sys_t *regs)
131{
132        serialcfg(&regs->eax.w[0], &regs->ecx.w[0], &regs->ebx.w[0]);
133}
134
135/*
136 * write_serial_str: write_serial for strings
137 */
138__export void write_serial_str(char *data)
139{
140        char ch;
141
142        while ((ch = *data++))
143                write_serial(ch);
144}
145
146/*
147 * pollchar: check if we have an input character pending
148 *
149 * Returns 1 if character pending.
150 */
151int bios_pollchar(void)
152{
153        com32sys_t ireg, oreg;
154        uint8_t data = 0;
155
156        memset(&ireg, 0, sizeof(ireg));
157
158        ireg.eax.b[1] = 0x11;   /* Poll keyboard */
159        __intcall(0x16, &ireg, &oreg);
160
161        if (!(oreg.eflags.l & EFLAGS_ZF))
162                return 1;
163
164        if (SerialPort) {
165                cli();
166
167                /* Already-queued input? */
168                if (SerialTail == SerialHead) {
169                        /* LSR */
170                        data = inb(SerialPort + 5) & 1;
171                        if (data) {
172                                /* MSR */
173                                data = inb(SerialPort + 6);
174
175                                /* Required status bits */
176                                data &= FlowIgnore;
177
178                                if (data == FlowIgnore)
179                                        data = 1;
180                                else
181                                        data = 0;
182                        }
183                } else
184                        data = 1;
185                sti();
186        }
187
188        return data;
189}
190
191__export int pollchar(void)
192{
193        return firmware->i_ops->pollchar();
194}
195
196void pm_pollchar(com32sys_t *regs)
197{
198        if (pollchar())
199                regs->eflags.l &= ~EFLAGS_ZF;
200        else
201                regs->eflags.l |= EFLAGS_ZF;
202}
203
204char bios_getchar(char *hi)
205{
206        com32sys_t ireg, oreg;
207        unsigned char data;
208
209        memset(&ireg, 0, sizeof(ireg));
210        memset(&oreg, 0, sizeof(oreg));
211        while (1) {
212                __idle();
213
214                ireg.eax.b[1] = 0x11;   /* Poll keyboard */
215                __intcall(0x16, &ireg, &oreg);
216
217                if (oreg.eflags.l & EFLAGS_ZF) {
218                        if (!SerialPort)
219                                continue;
220
221                        cli();
222                        if (SerialTail != SerialHead) {
223                                /* serial queued */
224                                sti(); /* We already know we'll consume data */
225                                data = *SerialTail++;
226
227                                if (SerialTail > SerialHead + serial_buf_size)
228                                        SerialTail = SerialHead;
229                        } else {
230                                /* LSR */
231                                data = inb(SerialPort + 5) & 1;
232                                if (!data) {
233                                        sti();
234                                        continue;
235                                }
236                                data = inb(SerialPort + 6);
237                                data &= FlowIgnore;
238                                if (data != FlowIgnore) {
239                                        sti();
240                                        continue;
241                                }
242
243                                data = inb(SerialPort);
244                                sti();
245                                break;
246                        }
247                } else {
248                        /* Keyboard input? */
249                        ireg.eax.b[1] = 0x10; /* Get keyboard input */
250                        __intcall(0x16, &ireg, &oreg);
251
252                        data = oreg.eax.b[0];
253                        *hi = oreg.eax.b[1];
254
255                        if (data == 0xE0)
256                                data = 0;
257
258                        if (data) {
259                                /* Convert character sets */
260                                data = KbdMap[data];
261                        }
262                }
263
264                break;
265        }
266
267        reset_idle();           /* Character received */
268        return data;
269}
270
271uint8_t bios_shiftflags(void)
272{
273        com32sys_t reg;
274        uint8_t ah, al;
275
276        memset(&reg, 0, sizeof reg);
277        reg.eax.b[1] = 0x12;
278        __intcall(0x16, &reg, &reg);
279        ah = reg.eax.b[1];
280        al = reg.eax.b[0];
281
282        /*
283         * According to the Interrupt List, "many machines" don't correctly
284         * fold the Alt state, presumably because it might be AltGr.
285         * Explicitly fold the Alt and Ctrl states; it fits our needs
286         * better.
287         */
288
289        if (ah & 0x0a)
290                al |= 0x08;
291        if (ah & 0x05)
292                al |= 0x04;
293
294        return al;
295}
296
297__export uint8_t kbd_shiftflags(void)
298{
299        if (firmware->i_ops->shiftflags)
300                return firmware->i_ops->shiftflags();
301        else
302                return 0;       /* Unavailable on this firmware */
303}
304
305/*
306 * getchar: Read a character from keyboard or serial port
307 */
308__export char getchar(char *hi)
309{
310        return firmware->i_ops->getchar(hi);
311}
312
313void pm_getchar(com32sys_t *regs)
314{
315        regs->eax.b[0] = getchar((char *)&regs->eax.b[1]);
316}
Note: See TracBrowser for help on using the repository browser.