direct-io.hg

changeset 15262:9766af047b6c

x86: Fix VBE EDID interrogation. Add a new boot option 'edid={no,force}'.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Tue Jun 12 11:04:27 2007 +0100 (2007-06-12)
parents 112703751b19
children feeca16435bf
files docs/src/user.tex xen/arch/x86/boot/cmdline.S xen/arch/x86/boot/video.S xen/arch/x86/setup.c
line diff
     1.1 --- a/docs/src/user.tex	Tue Jun 12 09:22:06 2007 +0100
     1.2 +++ b/docs/src/user.tex	Tue Jun 12 11:04:27 2007 +0100
     1.3 @@ -3188,6 +3188,13 @@ editing \path{grub.conf}.
     1.4    \end{description}
     1.5  The mode may optionally be followed by `{\bf,keep}' to cause Xen to keep
     1.6  writing to the VGA console after domain 0 starts booting (e.g., `vga=text-80x50,keep').
     1.7 +\item [ no-real-mode ] (x86 only) Do not execute real-mode bootstrap
     1.8 +  code when booting Xen. This option should not be used except for
     1.9 +  debugging. It will effectively disable the {\bf vga} option, which
    1.10 +  relies on real mode to set the video mode.
    1.11 +\item [ edid=no,force ] (x86 only) Either force retrieval of monitor
    1.12 +  EDID information via VESA DDC, or disable it (edid=no). This option
    1.13 +  should not normally be required except for debugging purposes.
    1.14  \item [ console\_to\_ring ] Place guest console output into the
    1.15    hypervisor console ring buffer. This is disabled by default.
    1.16    When enabled, both hypervisor output and guest console output
     2.1 --- a/xen/arch/x86/boot/cmdline.S	Tue Jun 12 09:22:06 2007 +0100
     2.2 +++ b/xen/arch/x86/boot/cmdline.S	Tue Jun 12 11:04:27 2007 +0100
     2.3 @@ -157,10 +157,10 @@ cmdline_parse_early:
     2.4          mov     sym_phys(multiboot_ptr),%ebx
     2.5          mov     MB_flags(%ebx),%eax
     2.6          test    $4,%al
     2.7 -        jz      1f
     2.8 +        jz      .Lcmdline_exit
     2.9          mov     MB_cmdline(%ebx),%eax
    2.10          test    %eax,%eax
    2.11 -        jz      1f
    2.12 +        jz      .Lcmdline_exit
    2.13  
    2.14          /* Check for 'no-real-mode' command-line option. */
    2.15          pushl   $sym_phys(.Lno_rm_opt)
    2.16 @@ -169,14 +169,40 @@ cmdline_parse_early:
    2.17          test    %eax,%eax
    2.18          setnz   bootsym_phys(skip_realmode)
    2.19  
    2.20 +        /* Check for 'edid=' command-line option. */
    2.21 +        movl    $sym_phys(.Ledid_opt),4(%esp)
    2.22 +        call    .Lfind_option
    2.23 +        test    %eax,%eax
    2.24 +        jz      .Lparse_vga
    2.25 +        cmpb    $'=',4(%eax)
    2.26 +        jne     .Lparse_vga
    2.27 +        add     $5,%eax
    2.28 +        mov     %eax,%ebx
    2.29 +        push    %ebx
    2.30 +        pushl   $sym_phys(.Ledid_force)
    2.31 +        call    .Lstr_prefix
    2.32 +        add     $8,%esp
    2.33 +        movb    $2,bootsym_phys(opt_edid) /* opt_edid=2: edid=force */
    2.34 +        test    %eax,%eax
    2.35 +        jz      .Lparse_vga
    2.36 +        push    %ebx
    2.37 +        pushl   $sym_phys(.Ledid_no)
    2.38 +        call    .Lstr_prefix
    2.39 +        add     $8,%esp
    2.40 +        decb    bootsym_phys(opt_edid)    /* opt_edid=1: edid=no */
    2.41 +        test    %eax,%eax
    2.42 +        jz      .Lparse_vga
    2.43 +        decb    bootsym_phys(opt_edid)    /* opt_edid=0: default */
    2.44 +
    2.45 +.Lparse_vga:
    2.46          /* Check for 'vga=' command-line option. */
    2.47          movl    $sym_phys(.Lvga_opt),4(%esp)
    2.48          call    .Lfind_option
    2.49          add     $8,%esp
    2.50          test    %eax,%eax
    2.51 -        jz      1f
    2.52 +        jz      .Lcmdline_exit
    2.53          cmpb    $'=',3(%eax)
    2.54 -        jne     1f
    2.55 +        jne     .Lcmdline_exit
    2.56          add     $4,%eax
    2.57  
    2.58          /* Found the 'vga=' option. Default option is to display vga menu. */
    2.59 @@ -189,7 +215,7 @@ cmdline_parse_early:
    2.60          call    .Lstr_prefix
    2.61          add     $8,%esp
    2.62          test    %eax,%eax
    2.63 -        jnz     3f
    2.64 +        jnz     .Lparse_vga_gfx
    2.65  
    2.66          /* We have 'vga=text-80x<rows>'. */
    2.67          add     $8,%ebx
    2.68 @@ -198,22 +224,23 @@ cmdline_parse_early:
    2.69          add     $4,%esp
    2.70          mov     %ax,%bx
    2.71          lea     sym_phys(.Lvga_text_modes),%esi
    2.72 -2:      lodsw
    2.73 +1:      lodsw
    2.74          test    %ax,%ax
    2.75 -        jz      1f
    2.76 +        jz      .Lcmdline_exit
    2.77          cmp     %ax,%bx
    2.78          lodsw
    2.79 -        jne     2b
    2.80 +        jne     1b
    2.81          mov     %ax,bootsym_phys(boot_vid_mode)
    2.82 -        jmp     1f
    2.83 +        jmp     .Lcmdline_exit
    2.84  
    2.85 +.Lparse_vga_gfx:
    2.86          /* Check for 'vga=gfx-<width>x<height>x<depth>'. */
    2.87 -3:      push    %ebx
    2.88 +        push    %ebx
    2.89          pushl   $sym_phys(.Lvga_gfx)
    2.90          call    .Lstr_prefix
    2.91          add     $8,%esp
    2.92          test    %eax,%eax
    2.93 -        jnz     3f
    2.94 +        jnz     .Lparse_vga_mode
    2.95  
    2.96          /* We have 'vga=gfx-<width>x<height>x<depth>'. */
    2.97          /* skip 'gfx-' */
    2.98 @@ -226,7 +253,7 @@ 3:      push    %ebx
    2.99          /* skip 'x' */
   2.100          lodsb
   2.101          cmpb    $'x',%al
   2.102 -        jne     1f
   2.103 +        jne     .Lcmdline_exit
   2.104          /* parse <height> */
   2.105          push    %esi
   2.106          call    .Latoi
   2.107 @@ -235,7 +262,7 @@ 3:      push    %ebx
   2.108          /* skip 'x' */
   2.109          lodsb
   2.110          cmpb    $'x',%al
   2.111 -        jne     1f
   2.112 +        jne     .Lcmdline_exit
   2.113          /* parse <depth> */
   2.114          push    %esi
   2.115          call    .Latoi
   2.116 @@ -243,15 +270,16 @@ 3:      push    %ebx
   2.117          mov     %ax,bootsym_phys(vesa_size)+4
   2.118          /* commit to vesa mode */
   2.119          movw    $VIDEO_VESA_BY_SIZE,bootsym_phys(boot_vid_mode)
   2.120 -        jmp     1f
   2.121 +        jmp     .Lcmdline_exit
   2.122  
   2.123 +.Lparse_vga_mode:
   2.124          /* Check for 'vga=mode-<mode>'. */
   2.125 -3:      push    %ebx
   2.126 +        push    %ebx
   2.127          pushl   $sym_phys(.Lvga_mode)
   2.128          call    .Lstr_prefix
   2.129          add     $8,%esp
   2.130          test    %eax,%eax
   2.131 -        jnz     1f
   2.132 +        jnz     .Lcmdline_exit
   2.133  
   2.134          /* We have 'vga=mode-<mode>'. */
   2.135          add     $5,%ebx
   2.136 @@ -260,7 +288,8 @@ 3:      push    %ebx
   2.137          add     $4,%esp
   2.138          mov     %ax,bootsym_phys(boot_vid_mode)
   2.139  
   2.140 -1:      popa
   2.141 +.Lcmdline_exit:
   2.142 +        popa
   2.143          ret
   2.144  
   2.145  .Lvga_text_modes: /* rows, mode_number */
   2.146 @@ -283,3 +312,9 @@ 1:      popa
   2.147          .asciz  "mode-"
   2.148  .Lno_rm_opt:
   2.149          .asciz  "no-real-mode"
   2.150 +.Ledid_opt:
   2.151 +        .asciz  "edid"
   2.152 +.Ledid_force:
   2.153 +        .asciz  "force"
   2.154 +.Ledid_no:
   2.155 +        .asciz  "no"
     3.1 --- a/xen/arch/x86/boot/video.S	Tue Jun 12 09:22:06 2007 +0100
     3.2 +++ b/xen/arch/x86/boot/video.S	Tue Jun 12 11:04:27 2007 +0100
     3.3 @@ -882,27 +882,18 @@ gettime:
     3.4  
     3.5  store_edid:
     3.6  #ifdef CONFIG_FIRMWARE_EDID
     3.7 -        pushw   %es                     # just save all registers
     3.8          pushw   %ax
     3.9          pushw   %bx
    3.10          pushw   %cx
    3.11          pushw   %dx
    3.12          pushw   %di
    3.13  
    3.14 -        pushw   %fs
    3.15 -        popw    %es
    3.16 -
    3.17 -        movl    $0x13131313, %eax       # memset block with 0x13
    3.18 -        movw    $32, %cx
    3.19 -        movw    $0x140, %di
    3.20 -        cld
    3.21 -        rep
    3.22 -        stosl
    3.23 +        cmpb    $1, bootsym(opt_edid)   # EDID disabled on cmdline (edid=no)?
    3.24 +        je      .Lno_edid
    3.25  
    3.26          cmpw    $0x0200, bootsym(vbe_version)  # only do EDID on >= VBE2.0
    3.27 -        jl      no_edid
    3.28 +        jl      .Lno_edid
    3.29  
    3.30 -        pushw   %es                     # save ES
    3.31          xorw    %di, %di                # Report Capability
    3.32          pushw   %di
    3.33          popw    %es                     # ES:DI must be 0:0
    3.34 @@ -910,31 +901,40 @@ store_edid:
    3.35          xorw    %bx, %bx
    3.36          xorw    %cx, %cx
    3.37          int     $0x10
    3.38 -        popw    %es                     # restore ES
    3.39 +        cmpw    $0x004f, %ax            # Call failed?
    3.40 +        jne     .Lno_edid
    3.41 +
    3.42 +        movw    %bx, bootsym(boot_edid_caps)
    3.43 +
    3.44 +        cmpb    $2, bootsym(opt_edid)   # EDID forced on cmdline (edid=force)?
    3.45 +        je      .Lforce_edid
    3.46  
    3.47 -        cmpb    $0x00, %ah              # call successful
    3.48 -        jne     no_edid
    3.49 +        /* EDID not forced on cmdline, so perform further sanity checks. */
    3.50 +        testb   $3,%bl                  # No DDC capabilities?
    3.51 +        jz      .Lno_edid
    3.52 +        cmpb    $5,%bh                  # Longer than 5s to read EDID?
    3.53 +        ja      .Lno_edid
    3.54  
    3.55 -        cmpb    $0x4f, %al              # function supported
    3.56 -        jne     no_edid
    3.57 -
    3.58 +.Lforce_edid:
    3.59          movw    $0x4f15, %ax            # do VBE/DDC
    3.60          movw    $0x01, %bx
    3.61          movw    $0x00, %cx
    3.62          movw    $0x00, %dx
    3.63 -        movw    $0x140, %di
    3.64 +        pushw   %ds
    3.65 +        popw    %es
    3.66 +        movw    $bootsym(boot_edid_info), %di
    3.67          int     $0x10
    3.68  
    3.69 -no_edid:
    3.70 +.Lno_edid:
    3.71          popw    %di                     # restore all registers
    3.72          popw    %dx
    3.73          popw    %cx
    3.74          popw    %bx
    3.75          popw    %ax
    3.76 -        popw    %es
    3.77  #endif
    3.78          ret
    3.79  
    3.80 +opt_edid:       .byte   0       # EDID parsing option (force/no/default)
    3.81  mt_end:         .word   0       # End of video mode table if built
    3.82  edit_buf:       .space  6       # Line editor buffer
    3.83  card_name:      .word   0       # Pointer to adapter name
    3.84 @@ -983,7 +983,7 @@ force_size:     .word   0       # Use th
    3.85  
    3.86  vesa_size:      .word   0,0,0   # width x depth x height
    3.87  
    3.88 -                .globl  boot_vid_info
    3.89 +                .globl  boot_vid_info, boot_edid_info, boot_edid_caps
    3.90  /* If we don't run at all, assume basic video mode 3 at 80x25. */
    3.91  boot_vid_mode:  .word   VIDEO_80x25
    3.92  boot_vid_info:  .byte   0, 0    /* orig_x, orig_y */
    3.93 @@ -992,3 +992,5 @@ boot_vid_info:  .byte   0, 0    /* orig_
    3.94                  .byte   1       /* isVGA          */
    3.95                  .word   16      /* 8x16 font      */
    3.96                  .fill   0x28,1,0
    3.97 +boot_edid_info: .fill   128,1,0x13
    3.98 +boot_edid_caps: .word   0x1313
     4.1 --- a/xen/arch/x86/setup.c	Tue Jun 12 09:22:06 2007 +0100
     4.2 +++ b/xen/arch/x86/setup.c	Tue Jun 12 11:04:27 2007 +0100
     4.3 @@ -47,6 +47,10 @@ extern void dmi_scan_machine(void);
     4.4  extern void generic_apic_probe(void);
     4.5  extern void numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn);
     4.6  
     4.7 +extern u16 boot_edid_caps;
     4.8 +extern u8 boot_edid_info[128];
     4.9 +extern struct boot_video_info boot_vid_info;
    4.10 +
    4.11  /*
    4.12   * opt_xenheap_megabytes: Size of Xen heap in megabytes, excluding the
    4.13   * page_info table and allocation bitmap.
    4.14 @@ -348,7 +352,6 @@ struct boot_video_info {
    4.15  
    4.16  static void __init parse_video_info(void)
    4.17  {
    4.18 -    extern struct boot_video_info boot_vid_info;
    4.19      struct boot_video_info *bvi = &bootsym(boot_vid_info);
    4.20  
    4.21      if ( (bvi->orig_video_isVGA == 1) && (bvi->orig_video_mode == 3) )
    4.22 @@ -444,20 +447,47 @@ void __init __start_xen(multiboot_info_t
    4.23  
    4.24      printk("Command line: %s\n", cmdline);
    4.25  
    4.26 +    printk("Video information:\n");
    4.27 +
    4.28 +    /* Print VGA display mode information. */
    4.29      switch ( vga_console_info.video_type )
    4.30      {
    4.31      case XEN_VGATYPE_TEXT_MODE_3:
    4.32 -        printk("VGA is text mode %dx%d, font 8x%d\n",
    4.33 +        printk(" VGA is text mode %dx%d, font 8x%d\n",
    4.34                 vga_console_info.u.text_mode_3.columns,
    4.35                 vga_console_info.u.text_mode_3.rows,
    4.36                 vga_console_info.u.text_mode_3.font_height);
    4.37          break;
    4.38      case XEN_VGATYPE_VESA_LFB:
    4.39 -        printk("VGA is graphics mode %dx%d, %d bpp\n",
    4.40 +        printk(" VGA is graphics mode %dx%d, %d bpp\n",
    4.41                 vga_console_info.u.vesa_lfb.width,
    4.42                 vga_console_info.u.vesa_lfb.height,
    4.43                 vga_console_info.u.vesa_lfb.bits_per_pixel);
    4.44          break;
    4.45 +    default:
    4.46 +        printk(" No VGA detected\n");
    4.47 +        break;
    4.48 +    }
    4.49 +
    4.50 +    /* Print VBE/DDC EDID information. */
    4.51 +    if ( bootsym(boot_edid_caps) != 0x1313 )
    4.52 +    {
    4.53 +        u16 caps = bootsym(boot_edid_caps);
    4.54 +        printk(" VBE/DDC methods:%s%s%s; ",
    4.55 +               (caps & 1) ? " V1" : "",
    4.56 +               (caps & 2) ? " V2" : "",
    4.57 +               !(caps & 3) ? " none" : "");
    4.58 +        printk("EDID transfer time: %d seconds\n", caps >> 8);
    4.59 +        if ( *(u32 *)bootsym(boot_edid_info) == 0x13131313 )
    4.60 +        {
    4.61 +            printk(" EDID info not retrieved because ");
    4.62 +            if ( !(caps & 3) )
    4.63 +                printk("no DDC retrieval method detected\n");
    4.64 +            else if ( (caps >> 8) > 5 )
    4.65 +                printk("takes longer than 5 seconds\n");
    4.66 +            else
    4.67 +                printk("of reasons unknown\n");
    4.68 +        }
    4.69      }
    4.70  
    4.71      /* Check that we have at least one Multiboot module. */