ports/116851: x11-drivers/xf86-video-mga - Xorg 7.3 mga driver fails to read video BIOS (G450 dual-VGA)

Warren Block wblock at wonkity.com
Fri Oct 5 10:00:13 PDT 2007


The following reply was made to PR ports/116851; it has been noted by GNATS.

From: Warren Block <wblock at wonkity.com>
To: bug-followup at FreeBSD.org
Cc:  
Subject: Re: ports/116851: x11-drivers/xf86-video-mga - Xorg 7.3 mga driver
 fails to read video BIOS (G450 dual-VGA)
Date: Fri, 5 Oct 2007 10:56:11 -0600 (MDT)

 A Solution: Reading The Matrox BIOS As A File
 
 
 
 The Problem
 
 The FreeBSD xorg drivers try to map the Matrox video BIOS into a PCI 
 range, but fail.  Something (OS? motherboard BIOS?) has mapped something 
 else into the available ranges, leaving none big enough to hold the 
 0x2000000 size wanted.  xf86GetRange (in xf86Bus.c) finds conflicts [tmp 
 = ChkConflict(&r,Acc,SETUP);] and the user sees this message in the Xorg 
 log:
 
 Requesting insufficient memory window!: start: 0xdee00000 end: 0xdfefffff size 0
 x2000000
 (EE) Cannot find empty range to map base to
 
 Without the BIOS, the mga driver has limited function.  This is 
 particularly important with the xorg 1.3 xrandr support for multihead 
 video boards (MGA450/550).  Newer versions of the mga driver use the 
 BIOS to determine how many video connectors the card has; without the 
 BIOS, only one is found.
 
 
 
 The Solution
 
 Well, maybe not *the* solution, but a solution.  The Linux folks fixed a
 similar problem back in April of 2006:
 
      https://bugs.freedesktop.org/show_bug.cgi?id=6751
 
 That code appears to have been integrated into xorg-server (linuxPci.c, 
 Pci.h, and Pci.c).
 
 This is a not-so-quick hack for FreeBSD based on that patch.  It seemed 
 like a quick port of the Linux code would work.  But it did not, due to 
 a) my inexperience with C; b) the complexity of X and multi-OS support 
 (lots of twisty little ARCH_INIT_OS_PCI ifdefs, all alike); c) my 
 inability to get pciconf to do what I wanted, and D) possibly badgers.
 
 So I'm documenting a hack that does work in the hopes that it will help 
 someone else implement it correctly.
 
 
 1. Copy the video BIOS from your card to a file.
 
 Real FreeBSD xorg code should read the BIOS data directly from the card. 
 Maybe pciconf can do that, but I couldn't figure out how, so I read it 
 from a file.  Use Linux to copy the BIOS to a file:
 
      $ lspci | grep Matrox
 
      (on my system this is 01:00.0)
 
      $ cd /sys/bus/pci/devices/0000:01:00.0
      $ echo 1 > rom
      $ cat rom > /tmp/videobios.bin
      $ echo 0 > rom
 
 Save the videobios.bin file somewhere (/tmp/mga/videobios.bin is where 
 the patch expects it) and reboot in FreeBSD.
 
 
 2. Patch xorg-server's Pci.c:
 
      # cd /usr/ports/x11-servers/xorg-server
      # copy patch-Pci.c (included at the end of this file) to files/
      # make install
 
 Of course this is wrong, the code should be in freebsdPci.c.  However, 
 adding the changes in the Linux diff was not enough, and the #ifdefs in 
 Pci.h defeated my attempts.  Somebody who knows what they are doing here 
 would probably have no trouble.
 
 
 3.  The Result
 
 Using the experimental mga-1.9.99, xorg log output shows:
 
 (II) Attempted to read BIOS 128KB from /tmp/mga/videobios.bin: got 34KB
 (--) MGA(0): Video BIOS info block at offset 0x07D00
 
 Output from xrandr 1.2:
 
 Screen 0: minimum 320 x 200, current 1280 x 1024, maximum 2304 x 1024
 VGA1 connected 1280x1024+0+0 375mm x 301mm
     1280x1024      60.0*+   59.9
     1024x768       70.1     60.0
     832x624        74.6
     800x600        72.2     75.0     60.3     56.2
     640x480        75.0     72.8     66.7     60.0
     720x400        70.1 
 VGA2 connected 1024x768+0+0 307mm x 230mm
     1024x768       60.0*+   75.1     70.1     60.0*
     832x624        74.6
     800x600        72.2     75.0     60.3     56.2
     640x480        75.0     72.8     66.7     60.0
     720x400        70.1
 
 
 The Patch
 
 --- hw/xfree86/os-support/bus/Pci.c.orig	2007-09-05 18:48:26.000000000 -0600
 +++ hw/xfree86/os-support/bus/Pci.c	2007-10-05 10:40:01.000000000 -0600
 @@ -210,6 +210,12 @@
   #include "xf86_OSproc.h"
   #include "Pci.h"
 
 +/* WB: start */
 +#include "compiler.h"
 +#include <stdio.h>
 +#include "xf86_OSlib.h"
 +/* WB: end */
 +
   #define PCI_MFDEV_SUPPORT   1 /* Include PCI multifunction device support */
   #define PCI_BRIDGE_SUPPORT  1 /* Include support for PCI-to-PCI bridges */
 
 @@ -238,6 +244,9 @@
   			unsigned char * buf, int len, PciBiosType BiosType );
 
   static int (*pciOSHandleBIOS)(PCITAG Tag, int basereg, unsigned char *buf, int len);
 +/* WB: start */
 +static int freebsdpciOsHandleBIOS(PCITAG Tag, int basereg, unsigned char *buf, int len);
 +/* WB: end */
 
   int xf86MaxPciDevs = 0;
 
 @@ -1324,6 +1333,13 @@
     PCITAG *pTag;
     int i;
 
 +  /* WB: start */
 +  /* this should be in pciOSHandleBIOS */
 +  n = freebsdpciOsHandleBIOS(Tag, basereg, buf, len);
 +  if (n)
 +      return n;
 +  /* WB: end */
 +
     /* fall back to the old code if the OS code fails */
     if (pciOSHandleBIOS) {
     	n = pciOSHandleBIOS(Tag, basereg, buf, len);
 @@ -1415,3 +1431,37 @@
   }
 
   #endif /* INCLUDE_XF86_NO_DOMAIN */
 +
 +/* WB: start */
 +/* MGA BIOS read code for example only, do not use for real.  Don't even look directly at it. */
 +#define BIOSFILE "/tmp/mga/videobios.bin"
 +
 +int freebsdpciOsHandleBIOS(PCITAG Tag, int basereg, unsigned char *buf, int len)
 +{
 +    unsigned int fd;
 +    struct stat st;
 +    int ret;
 +    int sofar = 0;
 +
 +    if (stat(BIOSFILE, &st) == 0)
 +    {
 +        if ((fd = open(BIOSFILE, O_RDWR)))
 +            basereg = 0x0;
 +
 +        lseek(fd, 0, SEEK_SET);
 +        do {
 +            /* copy the ROM until we hit Len, EOF or read error */
 +            ret = read(fd, buf+sofar, len-sofar);
 +            if (ret <= 0)
 +                break;
 +            sofar += ret;
 +        } while (sofar < len);
 +
 +        close(fd);
 +        if (sofar < len)
 +            xf86MsgVerb(X_INFO, 3, "Attempted to read BIOS %dKB from %s: got %dKB\n", len/1024, BIOSFILE, sofar/1024);
 +        return sofar;
 +    }
 +    return 0;
 +}
 +/* WB: end */
 
 -Warren Block * Rapid City, South Dakota USA


More information about the freebsd-x11 mailing list