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 18int 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 30static 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 40static 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 52void __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 63void __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 74static 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 */ 88int 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 99static 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 110void kbd_flush(void) 111{ 112 for (;;) { 113 if (!kbd_pending()) 114 break; 115 getchar(); 116 } 117} 118 119int 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