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 * -----------------------------------------------------------------------
18 * Console I/O code, except:
19 * writechr, writestr_early - module-dependent
20 * writestr, crlf - writestr.inc
21 * writehex* - writehex.inc
30 #include <syslinux/firmware.h>
36 union screen _screensize
;
39 * Serial console stuff.
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 */
48 __export
uint8_t DisplayMask
= 0x07; /* Display modes mask */
50 uint8_t ScrollAttribute
= 0x07; /* Grey on white (normal text color) */
53 * loadkeys: Load a LILO-style keymap
55 * Returns 0 on success, or -1 on error.
57 __export
int loadkeys(const char *filename
)
61 f
= fopen(filename
, "r");
65 fread(KbdMap
, 1, sizeof(KbdMap
), f
);
72 * write_serial: If serial output is enabled, write character on
75 __export
void write_serial(char data
)
80 if (!(DisplayMask
& 0x04))
86 ch
= inb(SerialPort
+ 5); /* LSR */
88 /* Wait for space in transmit register */
92 /* Wait for input flow control */
93 ch
= inb(SerialPort
+ 6);
101 outb(data
, SerialPort
); /* Send data */
105 void pm_write_serial(com32sys_t
*regs
)
107 write_serial(regs
->eax
.b
[0]);
110 void serialcfg(uint16_t *iobase
, uint16_t *divisor
, uint16_t *flowctl
)
114 *iobase
= SerialPort
;
115 *divisor
= BaudDivisor
;
127 *flowctl
= al
| (ah
<< 8);
130 void pm_serialcfg(com32sys_t
*regs
)
132 serialcfg(®s
->eax
.w
[0], ®s
->ecx
.w
[0], ®s
->ebx
.w
[0]);
136 * write_serial_str: write_serial for strings
138 __export
void write_serial_str(char *data
)
142 while ((ch
= *data
++))
147 * pollchar: check if we have an input character pending
149 * Returns 1 if character pending.
151 int bios_pollchar(void)
153 com32sys_t ireg
, oreg
;
156 memset(&ireg
, 0, sizeof(ireg
));
158 ireg
.eax
.b
[1] = 0x11; /* Poll keyboard */
159 __intcall(0x16, &ireg
, &oreg
);
161 if (!(oreg
.eflags
.l
& EFLAGS_ZF
))
167 /* Already-queued input? */
168 if (SerialTail
== SerialHead
) {
170 data
= inb(SerialPort
+ 5) & 1;
173 data
= inb(SerialPort
+ 6);
175 /* Required status bits */
178 if (data
== FlowIgnore
)
191 __export
int pollchar(void)
193 return firmware
->i_ops
->pollchar();
196 void pm_pollchar(com32sys_t
*regs
)
199 regs
->eflags
.l
&= ~EFLAGS_ZF
;
201 regs
->eflags
.l
|= EFLAGS_ZF
;
204 char bios_getchar(char *hi
)
206 com32sys_t ireg
, oreg
;
209 memset(&ireg
, 0, sizeof(ireg
));
210 memset(&oreg
, 0, sizeof(oreg
));
214 ireg
.eax
.b
[1] = 0x11; /* Poll keyboard */
215 __intcall(0x16, &ireg
, &oreg
);
217 if (oreg
.eflags
.l
& EFLAGS_ZF
) {
222 if (SerialTail
!= SerialHead
) {
224 sti(); /* We already know we'll consume data */
225 data
= *SerialTail
++;
227 if (SerialTail
> SerialHead
+ serial_buf_size
)
228 SerialTail
= SerialHead
;
231 data
= inb(SerialPort
+ 5) & 1;
236 data
= inb(SerialPort
+ 6);
238 if (data
!= FlowIgnore
) {
243 data
= inb(SerialPort
);
248 /* Keyboard input? */
249 ireg
.eax
.b
[1] = 0x10; /* Get keyboard input */
250 __intcall(0x16, &ireg
, &oreg
);
252 data
= oreg
.eax
.b
[0];
259 /* Convert character sets */
267 reset_idle(); /* Character received */
272 * getchar: Read a character from keyboard or serial port
274 __export
char getchar(char *hi
)
276 return firmware
->i_ops
->getchar(hi
);
279 void pm_getchar(com32sys_t
*regs
)
281 regs
->eax
.b
[0] = getchar((char *)®s
->eax
.b
[1]);