1/*- 2 * Copyright (c) 1998 Robert Nordier 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are freely 6 * permitted provided that the above copyright notice and this 7 * paragraph and the following disclaimer are duplicated in all 8 * such forms. 9 * 10 * This software is provided "AS IS" and without any express or 11 * implied warranties, including, without limitation, the implied 12 * warranties of merchantability and fitness for a particular 13 * purpose. 14 */ 15 16#include <sys/cdefs.h> 17__FBSDID("$FreeBSD: releng/11.0/sys/boot/i386/common/cons.c 296963 2016-03-16 23:12:19Z allanjude $"); 18 19#include <sys/param.h> 20 21#include <machine/psl.h> 22 23#include <btxv86.h> 24 25#include "lib.h" 26#include "rbx.h" 27#include "util.h" 28#include "cons.h" 29 30#define SECOND 18 /* Circa that many ticks in a second. */ 31 32uint8_t ioctrl = IO_KEYBOARD; 33 34void 35putc(int c) 36{ 37 38 v86.ctl = V86_FLAGS; 39 v86.addr = 0x10; 40 v86.eax = 0xe00 | (c & 0xff); 41 v86.ebx = 0x7; 42 v86int(); 43} 44 45void 46xputc(int c) 47{ 48 49 if (ioctrl & IO_KEYBOARD) 50 putc(c); 51 if (ioctrl & IO_SERIAL) 52 sio_putc(c); 53} 54 55void 56putchar(int c) 57{ 58 59 if (c == '\n') 60 xputc('\r'); 61 xputc(c); 62} 63 64int 65getc(int fn) 66{ 67 68 /* 69 * The extra comparison against zero is an attempt to work around 70 * what appears to be a bug in QEMU and Bochs. Both emulators 71 * sometimes report a key-press with scancode one and ascii zero 72 * when no such key is pressed in reality. As far as I can tell, 73 * this only happens shortly after a reboot. 74 */ 75 v86.ctl = V86_FLAGS; 76 v86.addr = 0x16; 77 v86.eax = fn << 8; 78 v86int(); 79 return fn == 0 ? v86.eax & 0xff : (!V86_ZR(v86.efl) && (v86.eax & 0xff)); 80} 81 82int 83xgetc(int fn) 84{ 85 86 if (OPT_CHECK(RBX_NOINTR)) 87 return (0); 88 for (;;) { 89 if (ioctrl & IO_KEYBOARD && getc(1)) 90 return (fn ? 1 : getc(0)); 91 if (ioctrl & IO_SERIAL && sio_ischar()) 92 return (fn ? 1 : sio_getc()); 93 if (fn) 94 return (0); 95 } 96 /* NOTREACHED */ 97} 98 99int 100getchar(void) 101{ 102 103 return (xgetc(0)); 104} 105 106int 107keyhit(unsigned int secs) 108{ 109 uint32_t t0, t1; 110 111 if (OPT_CHECK(RBX_NOINTR)) 112 return (0); 113 secs *= SECOND; 114 t0 = 0; 115 for (;;) { 116 if (xgetc(1)) 117 return (1); 118 if (secs > 0) { 119 t1 = *(uint32_t *)PTOV(0x46c); 120 if (!t0) 121 t0 = t1; 122 if (t1 < t0 || t1 >= t0 + secs) 123 return (0); 124 } 125 } 126 /* NOTREACHED */ 127} 128 129void 130getstr(char *cmdstr, size_t cmdstrsize) 131{ 132 char *s; 133 int c; 134 135 s = cmdstr; 136 for (;;) { 137 switch (c = xgetc(0)) { 138 case 0: 139 break; 140 case '\177': 141 case '\b': 142 if (s > cmdstr) { 143 s--; 144 printf("\b \b"); 145 } 146 break; 147 case '\n': 148 case '\r': 149 *s = 0; 150 return; 151 default: 152 if (s - cmdstr < cmdstrsize - 1) 153 *s++ = c; 154 putchar(c); 155 break; 156 } 157 } 158} 159