]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - lib_i386/realmode.c
AR405 board update
[karo-tx-uboot.git] / lib_i386 / realmode.c
index 27d469382507c0e0ae5b214ba7ab6c57f9fe498f..6cf273885b838ed55d1c2d02710a722ee4bc0f98 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * (C) Copyright 2002
  * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
- * 
+ *
  * See file CREDITS for list of people who contributed to this
  * project.
  *
 
 extern char realmode_enter;
 
+int realmode_setup(void)
+{
+       /* copy the realmode switch code */
+       if (i386boot_realmode_size > (REALMODE_MAILBOX-REALMODE_BASE)) {
+               printf("realmode switch too large (%ld bytes, max is %d)\n",
+                      i386boot_realmode_size, (REALMODE_MAILBOX-REALMODE_BASE));
+               return -1;
+       }
+
+       memcpy(REALMODE_BASE, (void*)i386boot_realmode, i386boot_realmode_size);
+       asm("wbinvd\n");
+
+       return 0;
+}
 
 int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out)
 {
-       
+
        /* setup out thin bios emulation */
        if (bios_setup()) {
                return -1;
        }
-               
-       /* copy the realmode switch code */
-       if (i386boot_realmode_size > (REALMODE_MAILBOX-REALMODE_BASE)) {
-               printf("realmode switch too large (%ld bytes, max is %d)\n", 
-                      i386boot_realmode_size, (int)(REALMODE_MAILBOX-REALMODE_BASE));
+
+       if (realmode_setup()) {
                return -1;
        }
-       
-       memcpy(REALMODE_BASE, (void*)i386boot_realmode, i386boot_realmode_size);
-               
-       
+
        in->eip = off;
        in->xcs = seg;
        if (3>(in->esp & 0xffff)) {
                printf("Warning: entering realmode with sp < 4 will fail\n");
        }
-       
+
        memcpy(REALMODE_MAILBOX, in, sizeof(struct pt_regs));
-       
-       __asm__ volatile ( 
+       asm("wbinvd\n");
+
+       __asm__ volatile (
                 "lcall $0x20,%0\n"  : :  "i" (&realmode_enter) );
 
+       asm("wbinvd\n");
        memcpy(out, REALMODE_MAILBOX, sizeof(struct pt_regs));
 
        return out->eax;
 }
 
+
+/* This code is supposed to access a realmode interrupt
+ * it does currently not work for me */
+int enter_realmode_int(u8 lvl, struct pt_regs *in, struct pt_regs *out)
+{
+       /* place two instructions at 0x700 */
+       writeb(0xcd, 0x700);  /* int $lvl */
+       writeb(lvl, 0x701);
+       writeb(0xcb, 0x702);  /* lret */
+       asm("wbinvd\n");
+
+       enter_realmode(0x00, 0x700, in, out);
+
+       return out->eflags&1;
+}