196ae6ea0SThomas Gleixner /* -*- linux-c -*- ------------------------------------------------------- * 296ae6ea0SThomas Gleixner * 396ae6ea0SThomas Gleixner * Copyright (C) 1991, 1992 Linus Torvalds 496ae6ea0SThomas Gleixner * Copyright 2007 rPath, Inc. - All Rights Reserved 596ae6ea0SThomas Gleixner * 696ae6ea0SThomas Gleixner * This file is part of the Linux kernel, and is made available under 796ae6ea0SThomas Gleixner * the terms of the GNU General Public License version 2. 896ae6ea0SThomas Gleixner * 996ae6ea0SThomas Gleixner * ----------------------------------------------------------------------- */ 1096ae6ea0SThomas Gleixner 1196ae6ea0SThomas Gleixner /* 1296ae6ea0SThomas Gleixner * arch/i386/boot/tty.c 1396ae6ea0SThomas Gleixner * 1496ae6ea0SThomas Gleixner * Very simple screen I/O 1596ae6ea0SThomas Gleixner * XXX: Probably should add very simple serial I/O? 1696ae6ea0SThomas Gleixner */ 1796ae6ea0SThomas Gleixner 1896ae6ea0SThomas Gleixner #include "boot.h" 1996ae6ea0SThomas Gleixner 2096ae6ea0SThomas Gleixner /* 2196ae6ea0SThomas Gleixner * These functions are in .inittext so they can be used to signal 2296ae6ea0SThomas Gleixner * error during initialization. 2396ae6ea0SThomas Gleixner */ 2496ae6ea0SThomas Gleixner 2596ae6ea0SThomas Gleixner void __attribute__((section(".inittext"))) putchar(int ch) 2696ae6ea0SThomas Gleixner { 2796ae6ea0SThomas Gleixner unsigned char c = ch; 2896ae6ea0SThomas Gleixner 2996ae6ea0SThomas Gleixner if (c == '\n') 3096ae6ea0SThomas Gleixner putchar('\r'); /* \n -> \r\n */ 3196ae6ea0SThomas Gleixner 3296ae6ea0SThomas Gleixner /* int $0x10 is known to have bugs involving touching registers 3396ae6ea0SThomas Gleixner it shouldn't. Be extra conservative... */ 3496ae6ea0SThomas Gleixner asm volatile("pushal; pushw %%ds; int $0x10; popw %%ds; popal" 3596ae6ea0SThomas Gleixner : : "b" (0x0007), "c" (0x0001), "a" (0x0e00|ch)); 3696ae6ea0SThomas Gleixner } 3796ae6ea0SThomas Gleixner 3896ae6ea0SThomas Gleixner void __attribute__((section(".inittext"))) puts(const char *str) 3996ae6ea0SThomas Gleixner { 4096ae6ea0SThomas Gleixner int n = 0; 4196ae6ea0SThomas Gleixner while (*str) { 4296ae6ea0SThomas Gleixner putchar(*str++); 4396ae6ea0SThomas Gleixner n++; 4496ae6ea0SThomas Gleixner } 4596ae6ea0SThomas Gleixner } 4696ae6ea0SThomas Gleixner 4796ae6ea0SThomas Gleixner /* 4896ae6ea0SThomas Gleixner * Read the CMOS clock through the BIOS, and return the 4996ae6ea0SThomas Gleixner * seconds in BCD. 5096ae6ea0SThomas Gleixner */ 5196ae6ea0SThomas Gleixner 5296ae6ea0SThomas Gleixner static u8 gettime(void) 5396ae6ea0SThomas Gleixner { 5496ae6ea0SThomas Gleixner u16 ax = 0x0200; 5596ae6ea0SThomas Gleixner u16 cx, dx; 5696ae6ea0SThomas Gleixner 5796ae6ea0SThomas Gleixner asm volatile("int $0x1a" 5896ae6ea0SThomas Gleixner : "+a" (ax), "=c" (cx), "=d" (dx) 5996ae6ea0SThomas Gleixner : : "ebx", "esi", "edi"); 6096ae6ea0SThomas Gleixner 6196ae6ea0SThomas Gleixner return dx >> 8; 6296ae6ea0SThomas Gleixner } 6396ae6ea0SThomas Gleixner 6496ae6ea0SThomas Gleixner /* 6596ae6ea0SThomas Gleixner * Read from the keyboard 6696ae6ea0SThomas Gleixner */ 6796ae6ea0SThomas Gleixner int getchar(void) 6896ae6ea0SThomas Gleixner { 6996ae6ea0SThomas Gleixner u16 ax = 0; 7096ae6ea0SThomas Gleixner asm volatile("int $0x16" : "+a" (ax)); 7196ae6ea0SThomas Gleixner 7296ae6ea0SThomas Gleixner return ax & 0xff; 7396ae6ea0SThomas Gleixner } 7496ae6ea0SThomas Gleixner 7596ae6ea0SThomas Gleixner static int kbd_pending(void) 7696ae6ea0SThomas Gleixner { 7796ae6ea0SThomas Gleixner u8 pending; 7896ae6ea0SThomas Gleixner asm volatile("int $0x16; setnz %0" 7996ae6ea0SThomas Gleixner : "=rm" (pending) 8096ae6ea0SThomas Gleixner : "a" (0x0100)); 8196ae6ea0SThomas Gleixner return pending; 8296ae6ea0SThomas Gleixner } 8396ae6ea0SThomas Gleixner 8496ae6ea0SThomas Gleixner void kbd_flush(void) 8596ae6ea0SThomas Gleixner { 8696ae6ea0SThomas Gleixner for (;;) { 8796ae6ea0SThomas Gleixner if (!kbd_pending()) 8896ae6ea0SThomas Gleixner break; 8996ae6ea0SThomas Gleixner getchar(); 9096ae6ea0SThomas Gleixner } 9196ae6ea0SThomas Gleixner } 9296ae6ea0SThomas Gleixner 9396ae6ea0SThomas Gleixner int getchar_timeout(void) 9496ae6ea0SThomas Gleixner { 9596ae6ea0SThomas Gleixner int cnt = 30; 9696ae6ea0SThomas Gleixner int t0, t1; 9796ae6ea0SThomas Gleixner 9896ae6ea0SThomas Gleixner t0 = gettime(); 9996ae6ea0SThomas Gleixner 10096ae6ea0SThomas Gleixner while (cnt) { 10196ae6ea0SThomas Gleixner if (kbd_pending()) 10296ae6ea0SThomas Gleixner return getchar(); 10396ae6ea0SThomas Gleixner 10496ae6ea0SThomas Gleixner t1 = gettime(); 10596ae6ea0SThomas Gleixner if (t0 != t1) { 10696ae6ea0SThomas Gleixner cnt--; 10796ae6ea0SThomas Gleixner t0 = t1; 10896ae6ea0SThomas Gleixner } 10996ae6ea0SThomas Gleixner } 11096ae6ea0SThomas Gleixner 11196ae6ea0SThomas Gleixner return 0; /* Timeout! */ 11296ae6ea0SThomas Gleixner } 113