vidconsole.c revision 38466
198752Sjmallett/* 298752Sjmallett * Copyright (c) 1998 Michael Smith (msmith@freebsd.org) 398755Sjmallett * Copyright (c) 1997 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp) 498755Sjmallett * All rights reserved. 598755Sjmallett * 698755Sjmallett * Redistribution and use in source and binary forms, with or without 798755Sjmallett * modification, are permitted provided that the following conditions 898752Sjmallett * are met: 998752Sjmallett * 1. Redistributions of source code must retain the above copyright 1098752Sjmallett * notice, this list of conditions and the following disclaimer. 1198752Sjmallett * 2. Redistributions in binary form must reproduce the above copyright 1298752Sjmallett * notice, this list of conditions and the following disclaimer in the 1398752Sjmallett * documentation and/or other materials provided with the distribution. 1498752Sjmallett * 1598752Sjmallett * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1698752Sjmallett * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1798812Sjmallett * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1898812Sjmallett * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1998812Sjmallett * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2098812Sjmallett * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21137587Snik * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2298812Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2398812Sjmallett * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24137587Snik * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2598812Sjmallett * SUCH DAMAGE. 2698812Sjmallett * 2798755Sjmallett * From Id: probe_keyboard.c,v 1.13 1997/06/09 05:10:55 bde Exp 2898755Sjmallett * 2998755Sjmallett * $Id$ 3098755Sjmallett */ 3198752Sjmallett 32263227Sjmmv#include <stand.h> 3398812Sjmallett 3498752Sjmallett#include <machine/cpufunc.h> 3598758Sjmallett 3698758Sjmallett#include "bootstrap.h" 3798758Sjmallett 3898812Sjmallett/* in vidconsole.S */ 3998758Sjmallettextern void vidputc(int c); 4098758Sjmallettextern int kbdgetc(void); 4198758Sjmallettextern int kbdiskey(void); 4298758Sjmallett 4398758Sjmallettstatic int probe_keyboard(void); 44263227Sjmmvstatic void vidc_probe(struct console *cp); 4598812Sjmallettstatic int vidc_init(int arg); 4698758Sjmallettstatic int vidc_in(void); 4798758Sjmallett 4898758Sjmallettstruct console vidconsole = { 4998758Sjmallett "vidconsole", 5098758Sjmallett "internal video/keyboard", 51137587Snik 0, 5298758Sjmallett vidc_probe, 5398758Sjmallett vidc_init, 5498755Sjmallett vidputc, 5598755Sjmallett vidc_in, 5698755Sjmallett kbdiskey 5798755Sjmallett}; 5898752Sjmallett 5998752Sjmallettstatic 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