Port-amd64 archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: HP BL465c G7 (2x Opteron 6172) doesn't boot install CD



Probably this is a problem with A20 and the keyboard controller

Can you try this patch, it is not well-tested especially not on different
motherboards but it got a DL385 G7 to load a kernel some time ago (it
still had problems, but could at least load the  kernel and start finding
devices).
The patch is loosely based on what linux does, I picked the same
adress to test, on the assumption it is a safe adress.

If someone who knows more about gate A20 can clean up this mess
I would be grateful.


This is a patch against current, it may not apply cleanly to 5.1,
in particular, i think the patch for cpufunc.S should be removed for 5.1
Also the bootroms will become too big so just try building the boot program
you need.

Index: sys/arch/i386/stand/lib/cpufunc.S
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/stand/lib/cpufunc.S,v
retrieving revision 1.4
diff -u -r1.4 cpufunc.S
--- sys/arch/i386/stand/lib/cpufunc.S   8 Jun 2011 16:03:42 -0000       1.4
+++ sys/arch/i386/stand/lib/cpufunc.S   2 Nov 2011 22:09:09 -0000
@@ -150,3 +150,7 @@
        outsl
        popl    %esi
        ret
+
+NENTRY(wbinvd)
+       wbinvd
+       ret
Index: sys/arch/i386/stand/lib/cpufunc.h
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/stand/lib/cpufunc.h,v
retrieving revision 1.2
diff -u -r1.2 cpufunc.h
--- sys/arch/i386/stand/lib/cpufunc.h   28 Apr 2008 20:23:25 -0000      1.2
+++ sys/arch/i386/stand/lib/cpufunc.h   2 Nov 2011 22:09:09 -0000
@@ -47,3 +47,5 @@
 void           outsw(unsigned, void *, int);
 void           outl(unsigned, uint32_t);
 void           outsl(unsigned, void *, int);
+
+void           wbinvd(void);
Index: sys/arch/i386/stand/lib/gatea20.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/stand/lib/gatea20.c,v
retrieving revision 1.12
diff -u -r1.12 gatea20.c
--- sys/arch/i386/stand/lib/gatea20.c   23 Aug 2009 12:31:05 -0000      1.12
+++ sys/arch/i386/stand/lib/gatea20.c   2 Nov 2011 22:09:09 -0000
@@ -25,6 +25,10 @@
                                           enable data line
                                           disable clock line */
 
+static void gateA20_92(void);
+static void gateA20_kbd(void);
+static int testa20(void);
+
 /*
  * Gate A20 for high memory
  */
@@ -34,7 +38,16 @@
 gateA20(void)
 {
        int biosA20(void);
-       u_long psl;
+
+       /*
+        * First, check if A2 is enabled.
+        */
+       printf("Test if A20 is already enabled\n");
+        if (testa20()) {
+               printf("A20 already enabled\n");
+               return;
+       } 
+       printf("A20 is not already enabled\n");
 
        /*
         * First, try asking the BIOS to enable A20.
@@ -45,36 +58,130 @@
         * and playing with port 0x92 may cause some systems to break.
         *
         * Otherwise, use the traditional method (keyboard controller).
+        * If that fails try port 0x92 anyway.
         */
-       if (!biosA20())
-               return;
-       psl = x86_read_psl();
-       x86_disable_intr();
+       unsigned temp;
+
+       printf("Try biosA20\n");
+       temp = biosA20();
+       if (!temp) {
+               if (testa20()) {
+                       printf("A20 biosA20 ok\n");
+                       return;
+               }
+               printf("A20 nok\n");
+       } else {
+               printf("biosA20 fail\n");
+       }
+
        if (
 #ifdef SUPPORT_PS2
            biosmca_ps2model == 0xf82 ||
 #endif
            (inb(K_STATUS) == 0xff && inb(K_RDWR) == 0xff)) {
-               int data;
+               gateA20_92();
+               if (testa20()) {
+                       printf("A20 92 ok\n");
+                       return;
+               }
+       }
 
-               data = inb(0x92);
-               outb(0x92, data | 0x2);
+       gateA20_kbd();
+       if (testa20()) {
+               printf("A20 kbd ok\n");
+               return;
        } else {
-               while (inb(K_STATUS) & K_IBUF_FUL);
+               printf("A20 kbd nok\n");
+       }
 
-               while (inb(K_STATUS) & K_OBUF_FUL)
-                       (void)inb(K_RDWR);
+       gateA20_92();
+       if (testa20()) {
+               printf("A20 92 ok\n");
+               return;
+       } else {
+               printf("A20 92 nok\n");
+       }
+       printf("failed to enable A20, reboot\n");
 
-               outb(K_CMD, KC_CMD_WOUT);
+       delay(10000);
+       reboot();
+}
 
-               while (inb(K_STATUS) & K_IBUF_FUL);
+void
+gateA20_92(void)
+{
+       u_long psl;
+       int data;
 
-               outb(K_RDWR, x_20);
+       psl = x86_read_psl();
+       x86_disable_intr();
 
-               while (inb(K_STATUS) & K_IBUF_FUL);
+       data = inb(0x92);
+       outb(0x92, data | 0x2);
+       x86_write_psl(psl);
+}
+
+static void
+gateA20_kbd(void)
+{
+       u_long psl;
+
+       psl = x86_read_psl();
+       x86_disable_intr();
+
+       while (inb(K_STATUS) & K_IBUF_FUL);
+
+       while (inb(K_STATUS) & K_OBUF_FUL)
+               (void)inb(K_RDWR);
+
+       outb(K_CMD, KC_CMD_WOUT);
+
+       while (inb(K_STATUS) & K_IBUF_FUL);
+
+       outb(K_RDWR, x_20);
+
+       while (inb(K_STATUS) & K_IBUF_FUL);
+
+       while (inb(K_STATUS) & K_OBUF_FUL)
+               (void)inb(K_RDWR);
 
-               while (inb(K_STATUS) & K_OBUF_FUL)
-                       (void)inb(K_RDWR);
-       }
        x86_write_psl(psl);
 }
+
+/*
+ * Test if A20 is enabled
+ * Returns 1 if A20 is enabled.
+ */
+static int
+testa20x(void)
+{
+       short *lo = (short *)0x200;
+       short * volatile hi = (short *)0x100200;
+       short oldval = *lo;
+       short i;
+
+       for (i = 0; i < 32; i++) {
+               *lo = i;
+               wbinvd();
+               if (*hi != i) {
+                       *lo = oldval;
+                       return 1;
+               }
+       }
+       *lo = oldval;
+       return 0;
+}
+static int
+testa20(void)
+{
+       int j;
+
+       for (j = 0; j < 10; j++) {
+               if (testa20x()) {
+                       printf("testa20: %d iter\n", j);
+                       return 1;
+               }
+       }
+       printf("testa20: failed\n");
+       return 0;
+}



Home | Main Index | Thread Index | Old Index