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

[Xen-devel] [PATCH 3/3] x86: real mode support: get EDID info



Obtain EDID info from BIOS and pass it up to Dom0.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>

Index: 2007-02-27/xen/arch/x86/Makefile
===================================================================
--- 2007-02-27.orig/xen/arch/x86/Makefile       2007-02-22 15:57:24.000000000 
+0100
+++ 2007-02-27/xen/arch/x86/Makefile    2007-02-22 15:48:44.000000000 +0100
@@ -78,7 +78,7 @@ xen.lds: $(TARGET_SUBARCH)/xen.lds.S $(H
 boot/mkelf32: boot/mkelf32.c
        $(HOSTCC) $(HOSTCFLAGS) -o $@ $<
 
-boot/$(TARGET_SUBARCH).o: boot/realmode.S boot/edd.S
+boot/$(TARGET_SUBARCH).o: boot/realmode.S boot/edd.S boot/video.S
 
 .PHONY: clean
 clean::
Index: 2007-02-27/xen/arch/x86/boot/realmode.S
===================================================================
--- 2007-02-27.orig/xen/arch/x86/boot/realmode.S        2007-02-22 
15:58:16.000000000 +0100
+++ 2007-02-27/xen/arch/x86/boot/realmode.S     2007-02-22 16:22:31.000000000 
+0100
@@ -140,4 +140,11 @@ eddbuf:                    .skip EDDMAXNR * (EDDEXTSIZE +
 edd_mbr_sig_buf:       .skip EDD_MBR_SIG_MAX * 4
 eddnr:                 .skip 1
 edd_mbr_sig_nr_buf:    .skip 1
+
+       .globl ddc_capabilities, edid_transfer_time, edid
+ddc_capabilities:      .skip 1
+edid_transfer_time:    .skip 1
+edid:                  .skip 128
        .previous
+
+#include "video.S"
Index: 2007-02-27/xen/arch/x86/boot/video.S
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 2007-02-27/xen/arch/x86/boot/video.S        2007-02-22 16:26:50.000000000 
+0100
@@ -0,0 +1,35 @@
+store_edid:
+       movl    $0x13131313, %eax               # memset block with 0x13
+       movw    $32, %cx
+       movw    $SYM_REAL(edid), %di
+       cld
+       rep
+       stosl
+
+       pushw   %es                             # save ES
+       xorw    %di, %di                        # Report Capability
+       movw    %di, %es                        # ES:DI must be 0:0
+       movw    $0x4f15, %ax
+       xorw    %bx, %bx
+       xorw    %cx, %cx
+       int     $0x10
+       popw    %es                             # restore ES
+
+       testb   %ah, %ah                        # call successful
+       jnz     no_edid
+
+       cmpb    $0x4f, %al                      # function supported
+       jne     no_edid
+
+       movb    %bl, SYM_REAL(ddc_capabilities)
+       movb    %bh, SYM_REAL(edid_transfer_time)
+
+       movw    $0x4f15, %ax                    # do VBE/DDC
+       movw    $0x01, %bx
+       xorw    %cx, %cx
+       xorw    %dx, %dx
+       movw    $SYM_REAL(edid), %di
+       int     $0x10
+
+no_edid:
+       ret
Index: 2007-02-27/xen/arch/x86/boot/x86_32.S
===================================================================
--- 2007-02-27.orig/xen/arch/x86/boot/x86_32.S  2007-02-21 18:08:44.000000000 
+0100
+++ 2007-02-27/xen/arch/x86/boot/x86_32.S       2007-02-22 16:28:03.000000000 
+0100
@@ -92,6 +92,8 @@ __start:
 
         pushl   $SYM_PHYS(edd)
         call    realmode
+        pushl   $SYM_PHYS(store_edid)
+        call    realmode
 
 #ifdef CONFIG_X86_PAE
         /* Initialize low and high mappings of all memory with 2MB pages */
Index: 2007-02-27/xen/arch/x86/boot/x86_64.S
===================================================================
--- 2007-02-27.orig/xen/arch/x86/boot/x86_64.S  2007-02-21 17:55:02.000000000 
+0100
+++ 2007-02-27/xen/arch/x86/boot/x86_64.S       2007-02-22 16:28:11.000000000 
+0100
@@ -75,6 +75,8 @@ __start:
         lss     SYM_PHYS(.Lstack_start),%esp
         pushl   $SYM_PHYS(edd)
         call    realmode
+        pushl   $SYM_PHYS(store_edid)
+        call    realmode
 
         /* We begin by interrogating the CPU for the presence of long mode. */
         mov     $0x80000000,%eax
Index: 2007-02-27/xen/arch/x86/platform_hypercall.c
===================================================================
--- 2007-02-27.orig/xen/arch/x86/platform_hypercall.c   2007-02-22 
16:14:39.000000000 +0100
+++ 2007-02-27/xen/arch/x86/platform_hypercall.c        2007-02-22 
16:22:49.000000000 +0100
@@ -24,10 +24,15 @@
 #include <asm/mtrr.h>
 #include "cpu/mtrr/mtrr.h"
 
+struct ddc {
+    uint8_t capabilities, edid_transfer_time, edid[128];
+};
+
 #ifndef COMPAT
 typedef long ret_t;
 DEFINE_SPINLOCK(xenpf_lock);
 struct edd edd;
+struct ddc ddc;
 # undef copy_from_compat
 # define copy_from_compat copy_from_guest
 # undef copy_to_compat
@@ -35,6 +40,7 @@ struct edd edd;
 #else
 extern spinlock_t xenpf_lock;
 extern struct edd edd;
+extern struct ddc ddc;
 #endif
 
 ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
@@ -219,6 +225,21 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe
             else
                 ret = -ESRCH;
             break;
+        case XEN_FW_DDC_INFO:
+            if ( op->u.firmware_info.index == 0 )
+            {
+                op->u.firmware_info.u.ddc_info.capabilities       = 
ddc.capabilities;
+                op->u.firmware_info.u.ddc_info.edid_transfer_time = 
ddc.edid_transfer_time;
+                if ( copy_field_to_guest(u_xenpf_op, op, 
u.firmware_info.u.ddc_info.capabilities) ||
+                     copy_field_to_guest(u_xenpf_op, op, 
u.firmware_info.u.ddc_info.edid_transfer_time) ||
+                     copy_to_compat(op->u.firmware_info.u.ddc_info.edid,
+                                    &ddc.edid[0],
+                                    ARRAY_SIZE(ddc.edid)) )
+                    ret = -EFAULT;
+            }
+            else
+                ret = -ESRCH;
+            break;
         default:
             ret = -EINVAL;
             break;
@@ -238,11 +259,17 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe
 #ifndef COMPAT
 static int __init firmware_init(void)
 {
+    extern uint8_t ddc_capabilities, edid_transfer_time, edid[];
+
     memcpy(edd.mbr_signature, edd_mbr_sig_buf, sizeof(edd.mbr_signature));
     memcpy(edd.edd_info, eddbuf, sizeof(edd.edd_info));
     edd.mbr_signature_nr = edd_mbr_sig_nr_buf;
     edd.edd_info_nr = eddnr;
 
+    ddc.capabilities = ddc_capabilities;
+    ddc.edid_transfer_time = edid_transfer_time;
+    memcpy(ddc.edid, edid, sizeof(ddc.edid));
+
     return 0;
 }
 __initcall(firmware_init);
Index: 2007-02-27/xen/include/public/platform.h
===================================================================
--- 2007-02-27.orig/xen/include/public/platform.h       2007-02-21 
14:51:00.000000000 +0100
+++ 2007-02-27/xen/include/public/platform.h    2007-02-22 16:10:04.000000000 
+0100
@@ -119,6 +119,7 @@ DEFINE_XEN_GUEST_HANDLE(xenpf_platform_q
 #define XEN_FW_EDD_INFO           2 /* from int 13 AH=41 */
 #define XEN_FW_EDD_PARAMS         3 /* from int 13 AH=48 */
 #define XEN_FW_MBR_SIGNATURE      4
+#define XEN_FW_DDC_INFO           5 /* from int 10 AX=4f15 */
 struct xenpf_firmware_info {
     /* IN variables. */
     uint32_t type;
@@ -138,6 +139,12 @@ struct xenpf_firmware_info {
         /* first uint16_t of buffer must be set to buffer size */
         XEN_GUEST_HANDLE(void) edd_params;
         uint32_t mbr_signature;
+        struct {
+            uint8_t capabilities;
+            uint8_t edid_transfer_time;
+            /* must refer to 128-byte buffer */
+            XEN_GUEST_HANDLE(uint8_t) edid;
+        } ddc_info;
     } u;
 };
 typedef struct xenpf_firmware_info xenpf_firmware_info_t;
Index: 2007-02-27/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c
===================================================================
--- 2007-02-27.orig/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c   
2007-02-22 16:38:02.000000000 +0100
+++ 2007-02-27/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c        
2007-02-22 16:43:00.000000000 +0100
@@ -155,6 +155,9 @@ struct sys_desc_table_struct {
 };
 struct edid_info edid_info;
 EXPORT_SYMBOL_GPL(edid_info);
+#ifndef CONFIG_XEN
+#define copy_edid() (edid_info = EDID_INFO)
+#endif
 struct ist_info ist_info;
 #if defined(CONFIG_X86_SPEEDSTEP_SMI) || \
        defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
@@ -1620,7 +1623,7 @@ void __init setup_arch(char **cmdline_p)
        ROOT_DEV = MKDEV(UNNAMED_MAJOR,0);
        drive_info = DRIVE_INFO;
        screen_info = SCREEN_INFO;
-       edid_info = EDID_INFO;
+       copy_edid();
        apm_info.bios = APM_BIOS_INFO;
        ist_info = IST_INFO;
        saved_videomode = VIDEO_MODE;
Index: 2007-02-27/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c
===================================================================
--- 2007-02-27.orig/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c 
2007-02-22 16:38:02.000000000 +0100
+++ 2007-02-27/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c      
2007-02-22 16:41:54.000000000 +0100
@@ -613,7 +613,7 @@ void __init setup_arch(char **cmdline_p)
        } else
                screen_info.orig_video_isVGA = 0;
 
-       edid_info = EDID_INFO;
+       copy_edid();
        saved_video_mode = SAVED_VIDEO_MODE;
        bootloader_type = LOADER_TYPE;
 
Index: 2007-02-27/linux-2.6-xen-sparse/drivers/xen/core/firmware.c
===================================================================
--- 2007-02-27.orig/linux-2.6-xen-sparse/drivers/xen/core/firmware.c    
2007-02-22 16:38:02.000000000 +0100
+++ 2007-02-27/linux-2.6-xen-sparse/drivers/xen/core/firmware.c 2007-02-22 
16:37:30.000000000 +0100
@@ -2,6 +2,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/edd.h>
+#include <video/edid.h>
 #include <xen/interface/platform.h>
 #include <asm/hypervisor.h>
 
@@ -59,3 +60,20 @@ void __init copy_edd(void)
        }
 }
 #endif
+
+void __init copy_edid(void)
+{
+#if defined(CONFIG_FIRMWARE_EDID) && defined(CONFIG_X86)
+       xen_platform_op_t op;
+
+       if (!is_initial_xendomain())
+               return;
+
+       op.cmd = XENPF_firmware_info;
+       op.u.firmware_info.index = 0;
+       op.u.firmware_info.type = XEN_FW_DDC_INFO;
+       set_xen_guest_handle(op.u.firmware_info.u.ddc_info.edid, 
edid_info.dummy);
+       if (HYPERVISOR_platform_op(&op) != 0)
+               memset(edid_info.dummy, 0x13, sizeof(edid_info.dummy));
+#endif
+}
Index: 2007-02-27/linux-2.6-xen-sparse/include/xen/firmware.h
===================================================================
--- 2007-02-27.orig/linux-2.6-xen-sparse/include/xen/firmware.h 2007-02-22 
16:38:02.000000000 +0100
+++ 2007-02-27/linux-2.6-xen-sparse/include/xen/firmware.h      2007-02-22 
16:32:13.000000000 +0100
@@ -2,5 +2,6 @@
 #define __XEN_FIRMWARE_H__
 
 void copy_edd(void);
+void copy_edid(void);
 
 #endif /* __XEN_FIRMWARE_H__ */



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.