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 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 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 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 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 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 */ 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 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 110 void kbd_flush(void) 111 { 112 for (;;) { 113 if (!kbd_pending()) 114 break; 115 getchar(); 116 } 117 } 118 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