vidconsole.c revision 40032
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.4 1998/10/07 02:39:06 msmith Exp $ 30 */ 31 32#include <stand.h> 33#include <bootstrap.h> 34#include <btxv86.h> 35#include <machine/psl.h> 36#include "libi386.h" 37 38#if KEYBOARD_PROBE 39#include <machine/cpufunc.h> 40 41static int probe_keyboard(void); 42#endif 43static void vidc_probe(struct console *cp); 44static int vidc_init(int arg); 45static void vidc_putchar(int c); 46static int vidc_getchar(void); 47static int vidc_ischar(void); 48 49struct console vidconsole = { 50 "vidconsole", 51 "internal video/keyboard", 52 0, 53 vidc_probe, 54 vidc_init, 55 vidc_putchar, 56 vidc_getchar, 57 vidc_ischar 58}; 59 60static void 61vidc_probe(struct console *cp) 62{ 63 64 /* look for a keyboard */ 65#if KEYBOARD_PROBE 66 if (probe_keyboard()) 67#endif 68 { 69 70 cp->c_flags |= C_PRESENTIN; 71 } 72 73 /* XXX for now, always assume we can do BIOS screen output */ 74 cp->c_flags |= C_PRESENTOUT; 75} 76 77static int 78vidc_init(int arg) 79{ 80 int i = 0; 81 82 while((i < 10) && (vidc_ischar())) 83 (void)vidc_getchar(); 84 return(0); /* XXX reinit? */ 85} 86 87static void 88vidc_putchar(int c) 89{ 90 v86.ctl = 0; 91 v86.addr = 0x10; 92 v86.eax = 0xe00 | c; 93 v86.ebx = 0x7; 94 v86int(); 95} 96 97static int 98vidc_getchar(void) 99{ 100 if (vidc_ischar()) { 101 v86.ctl = 0; 102 v86.addr = 0x16; 103 v86.eax = 0x0; 104 v86int(); 105 return(v86.eax & 0xff); 106 } else { 107 return(-1); 108 } 109} 110 111static int 112vidc_ischar(void) 113{ 114 v86.ctl = V86_FLAGS; 115 v86.addr = 0x16; 116 v86.eax = 0x100; 117 v86int(); 118 if (!(v86.efl & PSL_Z)) 119 return(v86.eax & 0xff); 120 return(0); 121} 122 123#if KEYBOARD_PROBE 124 125#define PROBE_MAXRETRY 5 126#define PROBE_MAXWAIT 400 127#define IO_DUMMY 0x84 128#define IO_KBD 0x060 /* 8042 Keyboard */ 129 130/* selected defines from kbdio.h */ 131#define KBD_STATUS_PORT 4 /* status port, read */ 132#define KBD_DATA_PORT 0 /* data port, read/write 133 * also used as keyboard command 134 * and mouse command port 135 */ 136#define KBDC_ECHO 0x00ee 137#define KBDS_ANY_BUFFER_FULL 0x0001 138#define KBDS_INPUT_BUFFER_FULL 0x0002 139#define KBD_ECHO 0x00ee 140 141/* 7 microsec delay necessary for some keyboard controllers */ 142static void 143delay7(void) 144{ 145 /* 146 * I know this is broken, but no timer is avaiable yet at this stage... 147 * See also comments in `delay1ms()'. 148 */ 149 inb(IO_DUMMY); inb(IO_DUMMY); 150 inb(IO_DUMMY); inb(IO_DUMMY); 151 inb(IO_DUMMY); inb(IO_DUMMY); 152} 153 154/* 155 * This routine uses an inb to an unused port, the time to execute that 156 * inb is approximately 1.25uS. This value is pretty constant across 157 * all CPU's and all buses, with the exception of some PCI implentations 158 * that do not forward this I/O adress to the ISA bus as they know it 159 * is not a valid ISA bus address, those machines execute this inb in 160 * 60 nS :-(. 161 * 162 */ 163static void 164delay1ms(void) 165{ 166 int i = 800; 167 while (--i >= 0) 168 (void)inb(0x84); 169} 170 171/* 172 * We use the presence/absence of a keyboard to determine whether the internal 173 * console can be used for input. 174 * 175 * Perform a simple test on the keyboard; issue the ECHO command and see 176 * if the right answer is returned. We don't do anything as drastic as 177 * full keyboard reset; it will be too troublesome and take too much time. 178 */ 179static int 180probe_keyboard(void) 181{ 182 int retry = PROBE_MAXRETRY; 183 int wait; 184 int i; 185 186 while (--retry >= 0) { 187 /* flush any noise */ 188 while (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) { 189 delay7(); 190 inb(IO_KBD + KBD_DATA_PORT); 191 delay1ms(); 192 } 193 194 /* wait until the controller can accept a command */ 195 for (wait = PROBE_MAXWAIT; wait > 0; --wait) { 196 if (((i = inb(IO_KBD + KBD_STATUS_PORT)) 197 & (KBDS_INPUT_BUFFER_FULL | KBDS_ANY_BUFFER_FULL)) == 0) 198 break; 199 if (i & KBDS_ANY_BUFFER_FULL) { 200 delay7(); 201 inb(IO_KBD + KBD_DATA_PORT); 202 } 203 delay1ms(); 204 } 205 if (wait <= 0) 206 continue; 207 208 /* send the ECHO command */ 209 outb(IO_KBD + KBD_DATA_PORT, KBDC_ECHO); 210 211 /* wait for a response */ 212 for (wait = PROBE_MAXWAIT; wait > 0; --wait) { 213 if (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) 214 break; 215 delay1ms(); 216 } 217 if (wait <= 0) 218 continue; 219 220 delay7(); 221 i = inb(IO_KBD + KBD_DATA_PORT); 222#ifdef PROBE_KBD_BEBUG 223 printf("probe_keyboard: got 0x%x.\n", i); 224#endif 225 if (i == KBD_ECHO) { 226 /* got the right answer */ 227 return (0); 228 } 229 } 230 231 return (1); 232} 233#endif /* KEYBOARD_PROBE */ 234