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