*BSD News Article 6300


Return to BSD News archive

Newsgroups: comp.unix.bsd
Path: sserve!manuel.anu.edu.au!munnari.oz.au!network.ucsd.edu!sdd.hp.com!zaphod.mps.ohio-state.edu!rpi!newsserver.pixel.kodak.com!psinntp!psinntp!l5next!scotty
From: scotty@gagetalker.com (Scott Turner)
Subject: Yet another pass at pc_probe
Message-ID: <1992Oct8.121604.809@gagetalker.com>
Sender: scotty@gagetalker.com
Organization: L5 Computing
Date: Thu, 8 Oct 1992 12:16:04 GMT
Lines: 91

OK, my '486 50MHz EISA system has a dirty secret,
it has one of those chintzy keyboard controllers.

After installing the beta patch kit I was left
with an unbootable system (the wd patches had to
be backed out.) but alas I had been a bad boy and
not made a floppy...

So rather than just use that DELAY() patch I
decided to figure out what the hell was going on.

The pc_probe code isn't reseting the a20. That is
only done in the bootstrap. The probe code is just
trying to reset the keyboard controller. Alas
the original code uses general purpose routines for
issuing the commands. These general purpose routines
read the keyboard controller and return the value.

Two things seem to go wrong, first, when reloading
the keyboard commands it appears you aren't supposed
to be reading the keyboard chip (at least with the chintzy
chips :) and the while loop was kinda awkward since it
ignored the value that came back from issuing the
reset command. I know this is bad with chintzy chips because
I was getting false "keyboard unplugged" messages on my
screen with the DELAY() patch.

And finally, the bootstrap code doesn't insist on a 
particular value be returned after the command is
acknowledged. It just waits for the keyboard chip to
have a value and then reads it.

So without further delay I present my wack at pc_probe.c:
*** pccons.c.orig       Thu Oct  8 04:54:35 1992
--- pccons.c    Thu Oct  8 04:55:05 1992
***************
*** 181,201 ****
        int again = 0;
  
        /* Enable interrupts and keyboard controller */
!       kbc_8042cmd(K_LDCMDBYTE);
!       outb(KBOUTP, CMDBYTE);
  
        /* Start keyboard stuff RESET */
!       kbd_cmd(KBC_RESET);
!       while((c = inb(KBDATAP)) != KBR_ACK) {
                if ((c == KBR_RESEND) ||  (c == KBR_OVERRUN)) {
                        if(!again)printf("KEYBOARD disconnected: RECONNECT  
\n");
-                       kbd_cmd(KBC_RESET);
                        again = 1;
                }
        }
  
        /* pick up keyboard reset return code */
!       while((c = inb(KBDATAP)) != KBR_RSTDONE);
        return 1;
  }
  
--- 169,189 ----
        int again = 0;
  
        /* Enable interrupts and keyboard controller */
!       while (inb(KBSTATP)&KBS_IBF); outb(KBSTATP,K_LDCMDBYTE);
!       while (inb(KBSTATP)&KBS_IBF); outb(KBDATAP,CMDBYTE);
  
        /* Start keyboard stuff RESET */
!       while((c = kbd_cmd(KBC_RESET)) != KBR_ACK) {
                if ((c == KBR_RESEND) ||  (c == KBR_OVERRUN)) {
                        if(!again)printf("KEYBOARD disconnected: RECONNECT  
\n");
                        again = 1;
                }
        }
  
        /* pick up keyboard reset return code */
!       while (inb(KBSTATP)&KBS_IBF);
!       (void) inb(KBDATAP);
! 
        return 1;
  }
  
Also, it's past 5am so I'm not going to touch it, but if I'm not
mistaken the following line is also in error:
 if ((c == KBR_RESEND) ||  (c == KBR_OVERRUN)) {

I think KBR_RESEND and KBR_OVERRUN #define's are the same. So
either this test needs to be simplified, or one of the #define's
is wrong.

Scotty