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$"); 18 19 #include <sys/param.h> 20 21 #include <machine/psl.h> 22 23 #include <btxv86.h> 24 25 #include "stand.h" 26 27 #include "lib.h" 28 #include "rbx.h" 29 #include "cons.h" 30 31 #define SECOND 18 /* Circa that many ticks in a second. */ 32 33 uint8_t ioctrl = IO_KEYBOARD; 34 35 void 36 putc(int c) 37 { 38 39 v86.ctl = V86_FLAGS; 40 v86.addr = 0x10; 41 v86.eax = 0xe00 | (c & 0xff); 42 v86.ebx = 0x7; 43 v86int(); 44 } 45 46 void 47 xputc(int c) 48 { 49 50 if (ioctrl & IO_KEYBOARD) 51 putc(c); 52 if (ioctrl & IO_SERIAL) 53 sio_putc(c); 54 } 55 56 static void 57 getcursor(int *row, int *col) 58 { 59 v86.ctl = V86_FLAGS; 60 v86.addr = 0x10; 61 v86.eax = 0x300; 62 v86.ebx = 0x7; 63 v86int(); 64 65 if (row != NULL) 66 *row = v86.edx >> 8; 67 if (col != NULL) 68 *col = v86.edx & 0xff; 69 } 70 71 void 72 putchar(int c) 73 { 74 int i, col; 75 76 switch (c) { 77 case '\n': 78 xputc('\r'); 79 break; 80 case '\t': 81 col = 0; 82 getcursor(NULL, &col); 83 col = 8 - (col % 8); 84 for (i = 0; i < col; i++) 85 xputc(' '); 86 return; 87 } 88 xputc(c); 89 } 90 91 int 92 getc(int fn) 93 { 94 95 v86.ctl = V86_FLAGS; 96 v86.addr = 0x16; 97 v86.eax = fn << 8; 98 v86int(); 99 100 if (fn == 0) 101 return (v86.eax); 102 103 if (V86_ZR(v86.efl)) 104 return (0); 105 return (v86.eax); 106 } 107 108 int 109 xgetc(int fn) 110 { 111 112 if (OPT_CHECK(RBX_NOINTR)) 113 return (0); 114 for (;;) { 115 if (ioctrl & IO_KEYBOARD && getc(1)) 116 return (fn ? 1 : getc(0)); 117 if (ioctrl & IO_SERIAL && sio_ischar()) 118 return (fn ? 1 : sio_getc()); 119 if (fn) 120 return (0); 121 } 122 /* NOTREACHED */ 123 } 124 125 int 126 getchar(void) 127 { 128 129 return (xgetc(0) & 0xff); 130 } 131 132 int 133 keyhit(unsigned int secs) 134 { 135 uint32_t t0, t1, c; 136 137 if (OPT_CHECK(RBX_NOINTR)) 138 return (0); 139 secs *= SECOND; 140 t0 = 0; 141 for (;;) { 142 /* 143 * The extra comparison is an attempt to work around 144 * what appears to be a bug in QEMU and Bochs. Both emulators 145 * sometimes report a key-press with scancode one and ascii zero 146 * when no such key is pressed in reality. As far as I can tell, 147 * this only happens shortly after a reboot. 148 */ 149 c = xgetc(1); 150 if (c != 0 && c != 0x0100) 151 return (1); 152 if (secs > 0) { 153 t1 = *(uint32_t *)PTOV(0x46c); 154 if (!t0) 155 t0 = t1; 156 if (t1 < t0 || t1 >= t0 + secs) 157 return (0); 158 } 159 } 160 /* NOTREACHED */ 161 } 162 163 void 164 getstr(char *cmdstr, size_t cmdstrsize) 165 { 166 char *s; 167 int c; 168 169 s = cmdstr; 170 for (;;) { 171 c = xgetc(0); 172 173 /* Translate some extended codes. */ 174 switch (c) { 175 case 0x5300: /* delete */ 176 c = '\177'; 177 break; 178 default: 179 c &= 0xff; 180 break; 181 } 182 183 switch (c) { 184 case '\177': 185 case '\b': 186 if (s > cmdstr) { 187 s--; 188 printf("\b \b"); 189 } 190 break; 191 case '\n': 192 case '\r': 193 *s = 0; 194 return; 195 default: 196 if (c >= 0x20 && c <= 0x7e) { 197 if (s - cmdstr < cmdstrsize - 1) 198 *s++ = c; 199 putchar(c); 200 } 201 break; 202 } 203 } 204 } 205