From owner-freebsd-hackers@FreeBSD.ORG Mon May 12 13:20:43 2003 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id C690737B404; Mon, 12 May 2003 13:20:43 -0700 (PDT) Received: from anuket.mj.niksun.com (gwnew.niksun.com [65.115.46.162]) by mx1.FreeBSD.org (Postfix) with ESMTP id 91AF643F75; Mon, 12 May 2003 13:20:42 -0700 (PDT) (envelope-from jkim@niksun.com) Received: from daemon.mj.niksun.com (daemon.mj.niksun.com [10.70.0.244]) h4CKK67F004054; Mon, 12 May 2003 16:20:06 -0400 (EDT) (envelope-from jkim@niksun.com) X-RAV-AntiVirus: This e-mail has been scanned for viruses. From: Jung-uk Kim Organization: Niksun, Inc. To: freebsd-hackers@freebsd.org Date: Mon, 12 May 2003 16:20:00 -0400 User-Agent: KMail/1.5.1 References: <200305091456.40582.jkim@niksun.com> In-Reply-To: <200305091456.40582.jkim@niksun.com> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200305121620.00049.jkim@niksun.com> cc: imp@freebsd.org Subject: Re: boot2 keyboard probing problem (with patch) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 12 May 2003 20:20:44 -0000 Is there anybody tried this yet? Probably it's my fault posting it on Friday. :-( Any (positive or negative) comments are welcome. Thanks, Jung-uk Kim On Friday 09 May 2003 02:56 pm, Jung-uk Kim wrote: > Recently I tried '-P' option in /boot.config for my desktop. boot2 > always said 'Keyboard: yes' even if I don't have a keyboard > attached. I realized the keyboard probing is somewhat broken for > many others, e. g., IBM x335. boot(8) says: > > Due to space constraints, the keyboard probe initiated by the -P > option is simply a test that the BIOS has detected an ``extended'' > keyboard. If an ``XT/AT'' keyboard (with no F11 and F12 keys, > etc.) is attached, the probe will fail. > > When I read src/sys/boot/i386/boot2/boot2.c, I found > > if (opts & 1 << RBX_PROBEKBD) { > i = *(uint8_t *)PTOV(0x496) & 0x10; > printf("Keyboard: %s\n", i ? "yes" : "no"); > if (!i) > opts |= 1 << RBX_DUAL | 1 << RBX_SERIAL; > opts &= ~(1 << RBX_PROBEKBD); > } > > This confirmed what the manpage said. The problem is 0x496 is set > by BIOS but recent BIOSes don't seem to set the flag after actual > probing (or they don't care?). I tried to resurrect KEYBOARD_PROBE > option (src/sys/boot/i386/libi386/vidconsole.c) but it didn't work > at all. Then I started writing my own and used some code from > keyboard_init() for Bochs BIOS, which is written by Adam Sulmicki > . > > http://www.eax.com/patches/BOCHS/bochs-bios-keyboard-2.1-diff > > My patch is simple: send echo command (0xee) to keyboard controller > and read it back from keyboard. If keyboard controller doesn't get > an echo back for some tries, it fails probing. > > BTW, I send 0 to port 0x80 (POST return value) to delay because I > couldn't find better way. A side effect is POST code will be reset > even if your BIOS reported a problem. However, if you got this far, > it shouldn't be a critical problem. ;-) Is there any better way to > delay? KEYBOARD_PROBE used port 0x84 but it was more tasteless > because we cannot know what it might be used for. (In fact, Compaq > used it for POST diagnostic.) > > This patch worked on my two desktops and an IBM 1U server. AT and > PS/2 keyboards should work. I think it would work with KVM, too. > The patch is against 4-STABLE but it could be okay with 5-CURRENT > if there is enough space left in boot2. ;-) > > Please try this patch and let me know if you find any issues or > have suggestions. > > Thanks, > > Jung-uk Kim --- src/sys/boot/i386/boot2/boot2.c.old Thu Oct 10 11:53:24 2002 +++ src/sys/boot/i386/boot2/boot2.c Fri May 9 03:45:46 2003 @@ -414,7 +414,64 @@ opts ^= 1 << flags[i]; } if (opts & 1 << RBX_PROBEKBD) { - i = *(uint8_t *)PTOV(0x496) & 0x10; + __asm __volatile ( + "\n\tmovb $2, %%ah\n\t" /* Wait for empty input buffer */ + "call wait\n\t" /* if %ah is 2 */ + "jmp flush\n" + "wait:\n\t" /* Wait for a buffer status */ + "xorw %%cx, %%cx\n" /* Initialize retry */ + "loop1:\n\t" + "decw %%cx\n\t" /* retry = 0xffff and retry-- */ + "jz exit1\n\t" /* Exit if retry is 0 */ + "inb $0x64, %%al\n\t" /* Check controller status */ + "testb $1, %%ah\n\t" /* Check output buffer status */ + "jnz output\n\t" /* if %ah is 1 */ + "testb %%ah, %%al\n\t" /* Input buffer empty? */ + "jz exit1\n\t" /* Exit if input buffer empty */ + "jmp delay\n" /* else delay */ + "output:\n\t" + "testb %%ah, %%al\n\t" /* Output buffer full? */ + "jnz exit1\n" /* Exit if output buffer full */ + "delay:\n\t" + "xorb %%al, %%al\n\t" /* XXX delay hack */ + "outb %%al, $0x80\n\t" /* Send 0 to port 0x80 (POST) */ + "jmp loop1\n" /* Retry */ + "exit1:\n\t" + "ret\n" + "flush:\n\t" + "movw $2001, %%cx\n" /* Initialize retry */ + "loop2:\n\t" + "decw %%cx\n\t" /* retry = 2000 and retry-- */ + "jz exit2\n\t" /* Exit if retry is 0 */ + "xorb %%al, %%al\n\t" /* XXX delay hack */ + "outb %%al, $0x80\n\t" /* Send 0 to port 0x80 (POST) */ + "inb $0x64, %%al\n\t" /* Check controller status */ + "testb $1, %%al\n\t" /* Any character to flush? */ + "jz loop2\n\t" /* Retry if buffer is empty */ + "inb $0x60, %%al\n\t" /* Flush a character from buffer */ + "movw $2001, %%cx\n\t" /* Reinitialize retry */ + "jmp loop2\n" /* Retry */ + "exit2:\n\t" + "movb $0xee, %%al\n\t" /* Set echo command */ + "outb %%al, $0x60\n\t" /* Send it! */ + "movb $2, %%ah\n\t" /* Wait for echo to be sent */ + "call wait\n\t" + "andw %%cx, %%cx\n\t" /* Is retry 0? */ + "jz fail\n\t" /* Echo not sent */ + "movb $1, %%ah\n\t" /* Wait for a character */ + "call wait\n\t" + "andw %%cx, %%cx\n\t" /* Is retry 0? */ + "jz fail\n\t" /* A character not received */ + "inb $0x60, %%al\n\t" /* Receive a character */ + "cmpb $0xee, %%al\n\t" /* Is this an echo? */ + "jne fail\n\t" /* Fail if echo not received */ + "movl $1, %0\n\t" /* Set return code = 1 */ + "jmp fine\n" /* and exit */ + "fail:\n\t" + "movl $0, %0\n" /* Set return code = 0 */ + "fine:\n" /* and exit */ + : "=r" (i) : : "ah", "al", "cx" + ); printf("Keyboard: %s\n", i ? "yes" : "no"); if (!i) opts |= 1 << RBX_DUAL | 1 << RBX_SERIAL;