1 /* -*- linux-c -*- ------------------------------------------------------- *
2  *
3  *   Copyright (C) 1991, 1992 Linus Torvalds
4  *   Copyright 2007 rPath, Inc. - All Rights Reserved
5  *   Copyright 2009 Intel Corporation; author H. Peter Anvin
6  *
7  *   This file is part of the Linux kernel, and is made available under
8  *   the terms of the GNU General Public License version 2.
9  *
10  * ----------------------------------------------------------------------- */
11 
12 /*
13  * Very simple screen and serial I/O
14  */
15 
16 #include "boot.h"
17 
18 int early_serial_base;
19 
20 #define XMTRDY          0x20
21 
22 #define TXR             0       /*  Transmit register (WRITE) */
23 #define LSR             5       /*  Line Status               */
24 
25 /*
26  * These functions are in .inittext so they can be used to signal
27  * error during initialization.
28  */
29 
serial_putchar(int ch)30 static void __attribute__((section(".inittext"))) serial_putchar(int ch)
31 {
32 	unsigned timeout = 0xffff;
33 
34 	while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
35 		cpu_relax();
36 
37 	outb(ch, early_serial_base + TXR);
38 }
39 
bios_putchar(int ch)40 static void __attribute__((section(".inittext"))) bios_putchar(int ch)
41 {
42 	struct biosregs ireg;
43 
44 	initregs(&ireg);
45 	ireg.bx = 0x0007;
46 	ireg.cx = 0x0001;
47 	ireg.ah = 0x0e;
48 	ireg.al = ch;
49 	intcall(0x10, &ireg, NULL);
50 }
51 
putchar(int ch)52 void __attribute__((section(".inittext"))) putchar(int ch)
53 {
54 	if (ch == '\n')
55 		putchar('\r');	/* \n -> \r\n */
56 
57 	bios_putchar(ch);
58 
59 	if (early_serial_base != 0)
60 		serial_putchar(ch);
61 }
62 
puts(const char * str)63 void __attribute__((section(".inittext"))) puts(const char *str)
64 {
65 	while (*str)
66 		putchar(*str++);
67 }
68 
69 /*
70  * Read the CMOS clock through the BIOS, and return the
71  * seconds in BCD.
72  */
73 
gettime(void)74 static u8 gettime(void)
75 {
76 	struct biosregs ireg, oreg;
77 
78 	initregs(&ireg);
79 	ireg.ah = 0x02;
80 	intcall(0x1a, &ireg, &oreg);
81 
82 	return oreg.dh;
83 }
84 
85 /*
86  * Read from the keyboard
87  */
getchar(void)88 int getchar(void)
89 {
90 	struct biosregs ireg, oreg;
91 
92 	initregs(&ireg);
93 	/* ireg.ah = 0x00; */
94 	intcall(0x16, &ireg, &oreg);
95 
96 	return oreg.al;
97 }
98 
kbd_pending(void)99 static int kbd_pending(void)
100 {
101 	struct biosregs ireg, oreg;
102 
103 	initregs(&ireg);
104 	ireg.ah = 0x01;
105 	intcall(0x16, &ireg, &oreg);
106 
107 	return !(oreg.eflags & X86_EFLAGS_ZF);
108 }
109 
kbd_flush(void)110 void kbd_flush(void)
111 {
112 	for (;;) {
113 		if (!kbd_pending())
114 			break;
115 		getchar();
116 	}
117 }
118 
getchar_timeout(void)119 int getchar_timeout(void)
120 {
121 	int cnt = 30;
122 	int t0, t1;
123 
124 	t0 = gettime();
125 
126 	while (cnt) {
127 		if (kbd_pending())
128 			return getchar();
129 
130 		t1 = gettime();
131 		if (t0 != t1) {
132 			cnt--;
133 			t0 = t1;
134 		}
135 	}
136 
137 	return 0;		/* Timeout! */
138 }
139 
140