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