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