Date: Fri, 5 Oct 2007 17:00:12 GMT From: Warren Block <wblock@wonkity.com> To: freebsd-x11@FreeBSD.org Subject: Re: ports/116851: x11-drivers/xf86-video-mga - Xorg 7.3 mga driver fails to read video BIOS (G450 dual-VGA) Message-ID: <200710051700.l95H0C3W052479@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR ports/116851; it has been noted by GNATS. From: Warren Block <wblock@wonkity.com> To: bug-followup@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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200710051700.l95H0C3W052479>