vidconsole.c revision 39896
1/* 2 * Copyright (c) 1998 Michael Smith (msmith@freebsd.org) 3 * Copyright (c) 1997 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp) 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * From Id: probe_keyboard.c,v 1.13 1997/06/09 05:10:55 bde Exp 28 * 29 * $Id: vidconsole.c,v 1.2 1998/09/17 23:52:10 msmith Exp $ 30 */ 31 32#include <stand.h> 33#include <bootstrap.h> 34#include <btxv86.h> 35#include "libi386.h" 36 37#if KEYBOARD_PROBE 38#include <machine/cpufunc.h> 39 40static int probe_keyboard(void); 41#endif 42static void vidc_probe(struct console *cp); 43static int vidc_init(int arg); 44static void vidc_putchar(int c); 45static int vidc_getchar(void); 46static int vidc_ischar(void); 47 48struct console vidconsole = { 49 "vidconsole", 50 "internal video/keyboard", 51 0, 52 vidc_probe, 53 vidc_init, 54 vidc_putchar, 55 vidc_getchar, 56 vidc_ischar 57}; 58 59static void 60vidc_probe(struct console *cp) 61{ 62 63 /* look for a keyboard */ 64#if KEYBOARD_PROBE 65 if (probe_keyboard()) 66#endif 67 { 68 69 cp->c_flags |= C_PRESENTIN; 70 } 71 72 /* XXX for now, always assume we can do BIOS screen output */ 73 cp->c_flags |= C_PRESENTOUT; 74} 75 76static int 77vidc_init(int arg) 78{ 79 return(0); /* XXX reinit? */ 80} 81 82static void 83vidc_putchar(int c) 84{ 85 v86.ctl = 0; 86 v86.addr = 0x10; 87 v86.eax = 0xe00 | c; 88 v86.ebx = 0x7; 89 v86int(); 90} 91 92static int 93vidc_getchar(void) 94{ 95 if (vidc_ischar()) { 96 v86.ctl = 0; 97 v86.addr = 0x16; 98 v86.eax = 0x0; 99 v86int(); 100 return(v86.eax & 0xff); 101 } else { 102 return(-1); 103 } 104} 105 106static int 107vidc_ischar(void) 108{ 109 v86.ctl = 0; 110 v86.addr = 0x16; 111 v86.eax = 0x100; 112 v86int(); 113 return(v86.eax); 114} 115 116#if KEYBOARD_PROBE 117 118#define PROBE_MAXRETRY 5 119#define PROBE_MAXWAIT 400 120#define IO_DUMMY 0x84 121#define IO_KBD 0x060 /* 8042 Keyboard */ 122 123/* selected defines from kbdio.h */ 124#define KBD_STATUS_PORT 4 /* status port, read */ 125#define KBD_DATA_PORT 0 /* data port, read/write 126 * also used as keyboard command 127 * and mouse command port 128 */ 129#define KBDC_ECHO 0x00ee 130#define KBDS_ANY_BUFFER_FULL 0x0001 131#define KBDS_INPUT_BUFFER_FULL 0x0002 132#define KBD_ECHO 0x00ee 133 134/* 7 microsec delay necessary for some keyboard controllers */ 135static void 136delay7(void) 137{ 138 /* 139 * I know this is broken, but no timer is avaiable yet at this stage... 140 * See also comments in `delay1ms()'. 141 */ 142 inb(IO_DUMMY); inb(IO_DUMMY); 143 inb(IO_DUMMY); inb(IO_DUMMY); 144 inb(IO_DUMMY); inb(IO_DUMMY); 145} 146 147/* 148 * This routine uses an inb to an unused port, the time to execute that 149 * inb is approximately 1.25uS. This value is pretty constant across 150 * all CPU's and all buses, with the exception of some PCI implentations 151 * that do not forward this I/O adress to the ISA bus as they know it 152 * is not a valid ISA bus address, those machines execute this inb in 153 * 60 nS :-(. 154 * 155 */ 156static void 157delay1ms(void) 158{ 159 int i = 800; 160 while (--i >= 0) 161 (void)inb(0x84); 162} 163 164/* 165 * We use the presence/absence of a keyboard to determine whether the internal 166 * console can be used for input. 167 * 168 * Perform a simple test on the keyboard; issue the ECHO command and see 169 * if the right answer is returned. We don't do anything as drastic as 170 * full keyboard reset; it will be too troublesome and take too much time. 171 */ 172static int 173probe_keyboard(void) 174{ 175 int retry = PROBE_MAXRETRY; 176 int wait; 177 int i; 178 179 while (--retry >= 0) { 180 /* flush any noise */ 181 while (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) { 182 delay7(); 183 inb(IO_KBD + KBD_DATA_PORT); 184 delay1ms(); 185 } 186 187 /* wait until the controller can accept a command */ 188 for (wait = PROBE_MAXWAIT; wait > 0; --wait) { 189 if (((i = inb(IO_KBD + KBD_STATUS_PORT)) 190 & (KBDS_INPUT_BUFFER_FULL | KBDS_ANY_BUFFER_FULL)) == 0) 191 break; 192 if (i & KBDS_ANY_BUFFER_FULL) { 193 delay7(); 194 inb(IO_KBD + KBD_DATA_PORT); 195 } 196 delay1ms(); 197 } 198 if (wait <= 0) 199 continue; 200 201 /* send the ECHO command */ 202 outb(IO_KBD + KBD_DATA_PORT, KBDC_ECHO); 203 204 /* wait for a response */ 205 for (wait = PROBE_MAXWAIT; wait > 0; --wait) { 206 if (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) 207 break; 208 delay1ms(); 209 } 210 if (wait <= 0) 211 continue; 212 213 delay7(); 214 i = inb(IO_KBD + KBD_DATA_PORT); 215#ifdef PROBE_KBD_BEBUG 216 printf("probe_keyboard: got 0x%x.\n", i); 217#endif 218 if (i == KBD_ECHO) { 219 /* got the right answer */ 220 return (0); 221 } 222 } 223 224 return (1); 225} 226#endif /* KEYBOARD_PROBE */ 227