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 #include <sys/param.h> 18 19 #include <machine/psl.h> 20 21 #include <btxv86.h> 22 23 #include "stand.h" 24 25 #include "lib.h" 26 #include "rbx.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 getchar(void) 125 { 126 127 return (xgetc(0) & 0xff); 128 } 129 130 int 131 keyhit(unsigned int secs) 132 { 133 uint32_t t0, t1, c; 134 135 if (OPT_CHECK(RBX_NOINTR)) 136 return (0); 137 secs *= SECOND; 138 t0 = 0; 139 for (;;) { 140 /* 141 * The extra comparison is an attempt to work around 142 * what appears to be a bug in QEMU and Bochs. Both emulators 143 * sometimes report a key-press with scancode one and ascii zero 144 * when no such key is pressed in reality. As far as I can tell, 145 * this only happens shortly after a reboot. 146 */ 147 c = xgetc(1); 148 if (c != 0 && c != 0x0100) 149 return (1); 150 if (secs > 0) { 151 t1 = *(uint32_t *)PTOV(0x46c); 152 if (!t0) 153 t0 = t1; 154 if (t1 < t0 || t1 >= t0 + secs) 155 return (0); 156 } 157 } 158 /* NOTREACHED */ 159 } 160 161 void 162 getstr(char *cmdstr, size_t cmdstrsize) 163 { 164 char *s; 165 int c; 166 167 s = cmdstr; 168 for (;;) { 169 c = xgetc(0); 170 171 /* Translate some extended codes. */ 172 switch (c) { 173 case 0x5300: /* delete */ 174 c = '\177'; 175 break; 176 default: 177 c &= 0xff; 178 break; 179 } 180 181 switch (c) { 182 case '\177': 183 case '\b': 184 if (s > cmdstr) { 185 s--; 186 printf("\b \b"); 187 } 188 break; 189 case '\n': 190 case '\r': 191 *s = 0; 192 return; 193 default: 194 if (c >= 0x20 && c <= 0x7e) { 195 if (s - cmdstr < cmdstrsize - 1) 196 *s++ = c; 197 putchar(c); 198 } 199 break; 200 } 201 } 202 } 203