Date: Mon, 12 May 2003 16:20:00 -0400 From: Jung-uk Kim <jkim@niksun.com> To: freebsd-hackers@freebsd.org Cc: imp@freebsd.org Subject: Re: boot2 keyboard probing problem (with patch) Message-ID: <200305121620.00049.jkim@niksun.com> In-Reply-To: <200305091456.40582.jkim@niksun.com> References: <200305091456.40582.jkim@niksun.com>
next in thread | previous in thread | raw e-mail | index | archive | help
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 > <adam@cfar.umd.edu>. > > 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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200305121620.00049.jkim>