boot2 keyboard probing problem (with patch)
Jung-uk Kim
jkim at niksun.com
Tue May 13 11:27:57 PDT 2003
I made a patch for 5-CURRENT and it is little bit clearer than the
previous version. (In fact, I haven't used x86 assembly for 10 years.
It is funny that the last assembly project was MBR for something
else. That said, please let me know if you see any weirdness.)
Unfortunately, 5-CURRENT's boot2 is more tighter because of UFS2
support. You will have to do 'make BOOT2_UFS=UFS1_ONLY' or 'make
BOOT2_UFS=UFS2_ONLY' to make the code usable.
- - - >8 - - - >8 - - - 5-CURRENT patch - - - >8 - - - >8 - - -
--- src/sys/boot/i386/boot2/boot2.c
+++ src/sys/boot/i386/boot2/boot2.c
@@ -371,7 +371,8 @@
char *arg = cmd;
char *p, *q;
unsigned int drv;
- int c, i;
+ int i;
+ uint8_t c;
while ((c = *arg++)) {
if (c == ' ' || c == '\t' || c == '\n')
@@ -387,7 +388,67 @@
opts ^= 1 << flags[i];
}
if (opts & 1 << RBX_PROBEKBD) {
+#ifdef UFS1_AND_UFS2
i = *(uint8_t *)PTOV(0x496) & 0x10;
+#else
+ uint8_t func;
+ uint16_t retry;
+ __asm __volatile (
+ "movb $2, %2\n\t" /* Wait for empty input buffer */
+ "call wait\n\t" /* if func is 2 */
+ "jmp flush\n"
+ "wait:\n\t" /* Wait for a buffer status */
+ "movw $0xffff, %3\n" /* Initialize retry */
+ "loop1:\n\t"
+ "inb $0x64, %1\n\t" /* Check controller status */
+ "testb $1, %2\n\t" /* Check output buffer status */
+ "jnz output\n\t" /* if func is 1 */
+ "testb %2, %1\n\t" /* Input buffer empty? */
+ "jz exit1\n\t" /* Exit if input buffer empty */
+ "jmp delay\n" /* else delay */
+ "output:\n\t"
+ "testb %2, %1\n\t" /* Output buffer full? */
+ "jnz exit1\n" /* Exit if output buffer full */
+ "delay:\n\t"
+ "xorb %1, %1\n\t" /* XXX delay hack */
+ "outb %1, $0x80\n\t" /* Send 0 to port 0x80 (POST) */
+ "loopw loop1\n" /* Retry */
+ "exit1:\n\t"
+ "ret\n"
+ "flush:\n\t"
+ "movw $2000, %3\n" /* Initialize retry */
+ "loop2:\n\t"
+ "xorb %1, %1\n\t" /* XXX delay hack */
+ "outb %1, $0x80\n\t" /* Send 0 to port 0x80 (POST) */
+ "inb $0x64, %1\n\t" /* Check controller status */
+ "testb $1, %1\n\t" /* Any character to flush? */
+ "jz again\n\t" /* Retry if buffer is empty */
+ "inb $0x60, %1\n\t" /* Flush a character from buffer */
+ "jmp flush\n" /* Reset counter and retry*/
+ "again:\n\t"
+ "loopw loop2\n" /* Retry */
+ "exit2:\n\t"
+ "movb $0xee, %1\n\t" /* Set echo command */
+ "outb %1, $0x60\n\t" /* Send it! */
+ "movb $2, %2\n\t" /* Wait for echo to be sent */
+ "call wait\n\t"
+ "andw %3, %3\n\t" /* Is retry 0? */
+ "jz fail\n\t" /* Echo not sent */
+ "movb $1, %2\n\t" /* Wait for a character */
+ "call wait\n\t"
+ "andw %3, %3\n\t" /* Is retry 0? */
+ "jz fail\n\t" /* A character not received */
+ "inb $0x60, %1\n\t" /* Receive a character */
+ "cmpb $0xee, %1\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"
+ "xorl %0, %0\n" /* Set return code = 0 */
+ "fine:" /* and exit */
+ : "=r" (i), "=a" (c), "=r" (func), "=c" (retry)
+ );
+#endif
printf("Keyboard: %s\n", i ? "yes" : "no");
if (!i)
opts |= 1 << RBX_DUAL | 1 << RBX_SERIAL;
- - - >8 - - - >8 - - - patch ends here - - - >8 - - - >8 - - -
Following patch is for 4-STABLE.
- - - >8 - - - >8 - - - 4-STABLE patch - - - >8 - - - >8 - - -
--- src/sys/boot/i386/boot2/boot2.c
+++ src/sys/boot/i386/boot2/boot2.c
@@ -398,7 +398,8 @@
parse(char *arg)
{
char *p, *q;
- int drv, c, i;
+ int drv, i;
+ uint8_t c;
while ((c = *arg++)) {
if (c == ' ' || c == '\t' || c == '\n')
@@ -414,7 +415,63 @@
opts ^= 1 << flags[i];
}
if (opts & 1 << RBX_PROBEKBD) {
- i = *(uint8_t *)PTOV(0x496) & 0x10;
+ uint8_t func;
+ uint16_t retry;
+ __asm __volatile (
+ "movb $2, %2\n\t" /* Wait for empty input buffer */
+ "call wait\n\t" /* if func is 2 */
+ "jmp flush\n"
+ "wait:\n\t" /* Wait for a buffer status */
+ "movw $0xffff, %3\n" /* Initialize retry */
+ "loop1:\n\t"
+ "inb $0x64, %1\n\t" /* Check controller status */
+ "testb $1, %2\n\t" /* Check output buffer status */
+ "jnz output\n\t" /* if func is 1 */
+ "testb %2, %1\n\t" /* Input buffer empty? */
+ "jz exit1\n\t" /* Exit if input buffer empty */
+ "jmp delay\n" /* else delay */
+ "output:\n\t"
+ "testb %2, %1\n\t" /* Output buffer full? */
+ "jnz exit1\n" /* Exit if output buffer full */
+ "delay:\n\t"
+ "xorb %1, %1\n\t" /* XXX delay hack */
+ "outb %1, $0x80\n\t" /* Send 0 to port 0x80 (POST) */
+ "loopw loop1\n" /* Retry */
+ "exit1:\n\t"
+ "ret\n"
+ "flush:\n\t"
+ "movw $2000, %3\n" /* Initialize retry */
+ "loop2:\n\t"
+ "xorb %1, %1\n\t" /* XXX delay hack */
+ "outb %1, $0x80\n\t" /* Send 0 to port 0x80 (POST) */
+ "inb $0x64, %1\n\t" /* Check controller status */
+ "testb $1, %1\n\t" /* Any character to flush? */
+ "jz again\n\t" /* Retry if buffer is empty */
+ "inb $0x60, %1\n\t" /* Flush a character from buffer */
+ "jmp flush\n" /* Reset counter and retry*/
+ "again:\n\t"
+ "loopw loop2\n" /* Retry */
+ "exit2:\n\t"
+ "movb $0xee, %1\n\t" /* Set echo command */
+ "outb %1, $0x60\n\t" /* Send it! */
+ "movb $2, %2\n\t" /* Wait for echo to be sent */
+ "call wait\n\t"
+ "andw %3, %3\n\t" /* Is retry 0? */
+ "jz fail\n\t" /* Echo not sent */
+ "movb $1, %2\n\t" /* Wait for a character */
+ "call wait\n\t"
+ "andw %3, %3\n\t" /* Is retry 0? */
+ "jz fail\n\t" /* A character not received */
+ "inb $0x60, %1\n\t" /* Receive a character */
+ "cmpb $0xee, %1\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"
+ "xorl %0, %0\n" /* Set return code = 0 */
+ "fine:" /* and exit */
+ : "=r" (i), "=a" (c), "=r" (func), "=c" (retry)
+ );
printf("Keyboard: %s\n", i ? "yes" : "no");
if (!i)
opts |= 1 << RBX_DUAL | 1 << RBX_SERIAL;
- - - >8 - - - >8 - - - patch ends here - - - >8 - - - >8 - - -
On Monday 12 May 2003 10:26 pm, M. Warner Losh wrote:
> I am away at a funeral with limited IP connectivity. reviewing
> assembler isn't something that I can do while travelling:-(
I am sorry to hear it. Just let me know when you find copious free
time.
Thanks,
Jung-uk Kim
> Warner
More information about the freebsd-hackers
mailing list