Hi,

As I reported some days ago in

  http://marc.theaimsgroup.com/?l=linux-kernel&m=100876129529834&q=raw

there are boot problems with new kernels on AMD SC410 processors. Symptom
is that the machine reboots right in the middle of the initialisation of
the serial port (indeed, right in the middle of a printk message).

In the meantime I've tracked down the problem, but cannot fully find the
origin. Here are some facts:

- The problem came in in 2.4.15. Linus has merged in some changes to
  the boot code by H. Peter Anvin (which basically are a Good Thing(TM)).
  They affect arch/i386/boot/setup.S.

- I could narrow it down to the A20 gate routines. My machine's BIOS
  doesn't seem to have the appropiate routine, so the algorithm falls
  back to using the keyboard controller method (which was also used
  in the old code).

- The problem seems to come from the code that waits for A20 gate to
  be _really_ enabled (shortly after a20_kbc:).

Attached is a experimental patch which demonstrates the problem: in line
687 you can change with a jump to "old_wait" or "new_wait" which routine
shall be used. With the old one the machine starts, with the new one it
reboots.

I must say I do not really understand what the problem is. First I thought
that maybe the loop counter overruns, but it doesn't seem to happen. I
have written the counter value to a port with LEDs and it seems to contain
"1" when the waiting loop detects the successful A20 switch.

Any idea would be helpful...

Robert
--
 +--------------------------------------------------------+
 | Dipl.-Ing. Robert Schwebel | http://www.pengutronix.de |
 | Pengutronix - Linux Solutions for Science and Industry |
 |   Braunschweiger Str. 79,  31134 Hildesheim, Germany   |
 |    Phone: +49-5121-28619-0 |  Fax: +49-5121-28619-4    |
 +--------------------------------------------------------+






--- setup-2.4.15.S      Fri Nov  9 22:58:02 2001
+++ setup.S     Fri Dec 21 21:49:50 2001
@@ -684,6 +684,62 @@
        outb    %al, $0x60
        call    empty_8042
 
+       jmp     new_wait
+
+# ----- old wait routine -----
+
+old_wait: 
+
+# wait until a20 really *is* enabled; it can take a fair amount of
+# time on certain systems; Toshiba Tecras are known to have this
+# problem.  The memory location used here (0x200) is the int 0x80
+# vector, which should be safe to use.
+
+
+       pushw   %dx
+       pushw   %cx
+       xorw    %dx,%dx
+       xorw    %cx,%cx
+
+        xorw    %ax, %ax                        # segment 0x0000
+        movw    %ax, %fs
+        decw    %ax                             # segment 0xffff (HMA)
+        movw    %ax, %gs
+a20_wait_old:
+       incw    %cx
+       jnz     goon
+       incw    %dx
+goon:  
+        incw    %ax                             # unused memory location <0xfff0
+        movw    %ax, %fs:(0x200)                # we use the "int 0x80" vector
+        cmpw    %gs:(0x210), %ax                # and its corresponding HMA addr
+        je      a20_wait_old                    # loop until no longer aliased
+
+       pushw   %ax
+
+       movb    $0xa5,%al                       # select PAMR...
+       outb    %al,$0x22                       # ... via CSCIR
+       movb    $0xff,%al                       # all lines are output
+       outb    %al,$0x23                       # ... on CSCDR
+
+       movb    $0xa9,%al                       # select PADR...
+       outb    %al,$0x22                       # ... via CSCIR
+       movb    %ch,%al                         #                               
+       outb    %al,$0x23
+
+       popw    %ax
+
+
+
+       popw    %cx
+       popw    %dx
+
+       jmp     rs_wait_done
+
+# ----- new wait routine -----
+
+new_wait: 
+
        # Wait until a20 really *is* enabled; it can take a fair amount of
        # time on certain systems; Toshiba Tecras are known to have this
        # problem.
@@ -694,6 +750,10 @@
        jnz     a20_done
        loop    a20_kbc_wait_loop
 
+rs_wait_done:
+
+# ----- end of wait -----
+
        # Final attempt: use "configuration port A"
 a20_fast:
        inb     $0x92, %al                      # Configuration Port A
@@ -909,12 +969,12 @@
        pushw   %cx
        pushw   %ax
        xorw    %cx, %cx
-       movw    %cx, %fs                        # Low memory
+       movw    %cx, %fs                        # Low memory (segment 0x0000)
        decw    %cx
-       movw    %cx, %gs                        # High memory area
+       movw    %cx, %gs                        # High memory area (segment 0xffff)
        movw    $A20_TEST_LOOPS, %cx
-       movw    %fs:(A20_TEST_ADDR), %ax
-       pushw   %ax
+       movw    %fs:(A20_TEST_ADDR), %ax        # put content of test address...
+       pushw   %ax                             # ... on stack
 a20_test_wait:
        incw    %ax
        movw    %ax, %fs:(A20_TEST_ADDR)

Reply via email to