vidconsole.c revision 38465
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$ 30 */ 31 32#include <stand.h> 33 34#include <machine/cpufunc.h> 35 36#include "bootstrap.h" 37 38/* in vidconsole.S */ 39extern void vidputc(int c); 40extern int kbdgetc(void); 41extern int kbdiskey(void); 42 43static int probe_keyboard(void); 44static void vidc_probe(struct console *cp); 45static int vidc_init(int arg); 46static int vidc_in(void); 47 48struct console vidconsole = { 49 "vidconsole", 50 "internal video/keyboard", 51 0, 52 vidc_probe, 53 vidc_init, 54 vidputc, 55 vidc_in, 56 kbdiskey 57}; 58 59static void 60vidc_probe(struct console *cp) 61{ 62 63 /* look for a keyboard */ 64#if 0 65 if (probe_keyboard()) { 66#else 67 if (1) { 68#endif 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 int 83vidc_in(void) 84{ 85 if (kbdiskey()) { 86 return(kbdgetc()); 87 } else { 88 return(-1); 89 } 90} 91 92#define PROBE_MAXRETRY 5 93#define PROBE_MAXWAIT 400 94#define IO_DUMMY 0x84 95#define IO_KBD 0x060 /* 8042 Keyboard */ 96 97/* selected defines from kbdio.h */ 98#define KBD_STATUS_PORT 4 /* status port, read */ 99#define KBD_DATA_PORT 0 /* data port, read/write 100 * also used as keyboard command 101 * and mouse command port 102 */ 103#define KBDC_ECHO 0x00ee 104#define KBDS_ANY_BUFFER_FULL 0x0001 105#define KBDS_INPUT_BUFFER_FULL 0x0002 106#define KBD_ECHO 0x00ee 107 108/* 7 microsec delay necessary for some keyboard controllers */ 109static void 110delay7(void) 111{ 112 /* 113 * I know this is broken, but no timer is avaiable yet at this stage... 114 * See also comments in `delay1ms()'. 115 */ 116 inb(IO_DUMMY); inb(IO_DUMMY); 117 inb(IO_DUMMY); inb(IO_DUMMY); 118 inb(IO_DUMMY); inb(IO_DUMMY); 119} 120 121/* 122 * This routine uses an inb to an unused port, the time to execute that 123 * inb is approximately 1.25uS. This value is pretty constant across 124 * all CPU's and all buses, with the exception of some PCI implentations 125 * that do not forward this I/O adress to the ISA bus as they know it 126 * is not a valid ISA bus address, those machines execute this inb in 127 * 60 nS :-(. 128 * 129 */ 130static void 131delay1ms(void) 132{ 133 int i = 800; 134 while (--i >= 0) 135 (void)inb(0x84); 136} 137 138/* 139 * We use the presence/absence of a keyboard to determine whether the internal 140 * console can be used for input. 141 * 142 * Perform a simple test on the keyboard; issue the ECHO command and see 143 * if the right answer is returned. We don't do anything as drastic as 144 * full keyboard reset; it will be too troublesome and take too much time. 145 */ 146static int 147probe_keyboard(void) 148{ 149 int retry = PROBE_MAXRETRY; 150 int wait; 151 int i; 152 153 while (--retry >= 0) { 154 /* flush any noise */ 155 while (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) { 156 delay7(); 157 inb(IO_KBD + KBD_DATA_PORT); 158 delay1ms(); 159 } 160 161 /* wait until the controller can accept a command */ 162 for (wait = PROBE_MAXWAIT; wait > 0; --wait) { 163 if (((i = inb(IO_KBD + KBD_STATUS_PORT)) 164 & (KBDS_INPUT_BUFFER_FULL | KBDS_ANY_BUFFER_FULL)) == 0) 165 break; 166 if (i & KBDS_ANY_BUFFER_FULL) { 167 delay7(); 168 inb(IO_KBD + KBD_DATA_PORT); 169 } 170 delay1ms(); 171 } 172 if (wait <= 0) 173 continue; 174 175 /* send the ECHO command */ 176 outb(IO_KBD + KBD_DATA_PORT, KBDC_ECHO); 177 178 /* wait for a response */ 179 for (wait = PROBE_MAXWAIT; wait > 0; --wait) { 180 if (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) 181 break; 182 delay1ms(); 183 } 184 if (wait <= 0) 185 continue; 186 187 delay7(); 188 i = inb(IO_KBD + KBD_DATA_PORT); 189#ifdef PROBE_KBD_BEBUG 190 printf("probe_keyboard: got 0x%x.\n", i); 191#endif 192 if (i == KBD_ECHO) { 193 /* got the right answer */ 194 return (0); 195 } 196 } 197 198 return (1); 199} 200