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