mga-1.4.7 fails to read the video BIOS of a Matrox G450 dual-VGA AGP card: (--) MGA(0): Chipset: "mgag400" (G450) (==) MGA(0): Depth 24, (==) framebuffer bpp 32 (==) MGA(0): RGB weight 888 (==) MGA(0): Using AGP 1x mode (==) MGA(0): Using XAA acceleration (--) MGA(0): Linear framebuffer at 0xDC000000 (==) MGA(0): MMIO registers at 0xDFEFC000 (--) MGA(0): Pseudo-DMA transfer window at 0xDF000000 (--) MGA(0): BIOS at 0xDFEC0000 Requesting insufficient memory window!: start: 0xdee00000 end: 0xdfefffff size 0x2000000 (EE) Cannot find empty range to map base to (WW) MGA(0): Video BIOS info block not detected! The driver still works, but without the BIOS, features of the card like more than one VGA port are not available. The same computer running the 200709 snapshot of FreeBSD 7.0-CURRENT showed the same failure. A Knoppix Linux liveCD with Xorg 7.2 on the same computer was able to read the BIOS: (--) MGA(0): BIOS at 0xDFEC0000 (II) Attempted to read BIOS 64KB from /sys/bus/pci/devices/0000:01:00.0/rom: got 34KB (--) MGA(0): Video BIOS info block at offset 0x07D00 From crude testing, it appears that the problem may be in the xorg-server freebsdPci.c routine (xorg-server-1.4/hw/xfree86/os-support/bus/freebsdPci.c) Further information: Excerpt from 'pciconf -lv': agp0@pci0:0:0: class=0x060000 card=0x00001106 chip=0x31891106 rev=0x80 hdr=0x00 vendor = 'VIA Technologies Inc' device = 'VT8377 Apollo KT400/A/600 CPU to PCI Bridge' class = bridge subclass = HOST-PCI pcib1@pci0:1:0: class=0x060400 card=0x00000000 chip=0xb1981106 rev=0x00 hdr=0x01 vendor = 'VIA Technologies Inc' device = 'ProSavageDDR P4X600 CPU to AGP Bridge' class = bridge subclass = PCI-PCI drm0@pci1:0:0: class=0x030000 card=0x0641102b chip=0x0525102b rev=0x82 hdr=0x00 vendor = 'Matrox Electronic Systems Ltd.' device = 'MGA G450 Dual Head Chip of G450 graphics card' class = display subclass = VGA drm output on ttyv0: drm0: <Matrox G400/G450 (AGP)> mem 0xdc000000-0xddffffff,0xdfefc000-0xdfefffff,0xdf000000-0xdf7fffff irq 16 at device 0.0 on pci1 info: [drm] AGP at 0xe0000000 128MB info: [drm] Initialized mga 3.2.2 20060319 info: [drm] Initialized card for AGP DMA. How-To-Repeat: Install Xorg 7.3 on FreeBSD computer with Matrox G450 card. startx Note 'Video BIOS info block not detected!' message in /var/log/Xorg.0.log.
Responsible Changed From-To: freebsd-ports-bugs->freebsd-x11 Over to maintainer (via the GNATS Auto Assign Tool) http://www.freebsd.org/cgi/query-pr.cgi?pr=116851 Adding to audit trail from misfiled PR ports/116915: Date: Thu, 4 Oct 2007 10:16:28 -0600 (MDT)
The same happens with G550: (--) MGA(0): Chipset: "mgag550" (**) MGA(0): Depth 24, (--) framebuffer bpp 32 (==) MGA(0): RGB weight 888 (**) MGA(0): Option "HWcursor" "off" (**) MGA(0): Option "AGPMode" "4" (**) MGA(0): Using AGP 4x mode (==) MGA(0): Using XAA acceleration (--) MGA(0): Linear framebuffer at 0xFA000000 (**) MGA(0): MMIO registers at 0xF9000000 (--) MGA(0): Pseudo-DMA transfer window at 0xF8800000 (--) MGA(0): BIOS at 0xF9FE0000 Requesting insufficient memory window!: start: 0xf8800000 end: 0xf9efffff size 0x2000000 (EE) Cannot find empty range to map base to (WW) MGA(0): Video BIOS info block not detected ! and the second head is working only in clone mode.
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
When the FreeBSD port of xorg-server starts using libpciaccess, the problem reading the video BIOS ROM should be fixed. Until then, I have an easier patch and instructions for xorg-server 1.4.1: http://www.wonkity.com/~wblock/mgapatch/xorg-patch.txt -Warren Block * Rapid City, South Dakota USA
State Changed From-To: open->closed I'm closing this PR cause there's no easy way to fix this in the ports collection right now. Please work with xorg maintainers to get your patches in the git repo. If it's committed to master but too late for 1.4.1, I'll reconsider adding it as a local patch. In the meantime, I've rolled back the mga driver to 1.4.7 as it seems to fix all single-head issues. Thanks for your submission.