NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
xsrc/48796: xf86-video-mga: bug with dual-head operations
>Number: 48796
>Category: xsrc
>Synopsis: xf86-video-mga: bug with dual-head operations
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: xsrc-manager
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri May 09 14:20:00 +0000 2014
>Originator: Volkmar Seifert
>Release: NetBSD 6.1_STABLE
>Organization:
>Environment:
NetBSD SnowLion.home.nifelheim.info 6.1_STABLE NetBSD 6.1_STABLE (GENERIC) #1:
Fri May 9 12:48:47 CEST 2014
mjoellnir@cheetah:/work/netbsd/v6/work/i386/GENERIC/obj/work/netbsd/v6/src/sys/arch/i386/compile/GENERIC
i386
>Description:
The mga driver fails on dual head configurations with this error:
[ 1099.472] (WW) MGA(0): Direct rendering disabled
[ 1099.473] (EE) MGA(1): Unable to map BAR 0. Invalid argument (22)
[ 1099.473]
Fatal server error:
[ 1099.473] AddScreen/ScreenInit failed for driver 1
This happens, because it tries to map the same PCI memory region twice.
The xorg.config looks like this (shortened to the relevant sections):
Section "Monitor"
Identifier "Monitor0"
VendorName "Acer"
ModelName "V223HQ"
EndSection
Section "Monitor"
Identifier "Monitor1"
VendorName "Asus"
ModelName "V278"
EndSection
Section "Device"
Identifier "Card0"
Driver "mga"
#BusId "PCI:1:0:0"
Screen 0
EndSection
Section "Device"
Identifier "Card1"
Driver "mga"
#BusID "PCI:1:0:0"
Screen 1
EndSection
Section "Screen"
Identifier "Screen0"
Device "Card0"
Monitor "Monitor0"
DefaultDepth 24
EndSection
Section "Screen"
Identifier "Screen1"
Device "Card1"
Monitor "Monitor1"
DefaultDepth 24
EndSection
Section "ServerLayout"
Identifier "X.org Configured"
InputDevice "Mouse0" "CorePointer"
InputDevice "Keyboard0" "CoreKeyboard"
Screen "Screen0"
Screen "Screen1" RightOf "Screen0"
EndSection
Section "ServerFlags"
Option "Xinerama"
EndSection
>How-To-Repeat:
Use a xorg.conf like the one above and an MGA card, call "startx" on cli, and
there you go.
>Fix:
Following a few leads found via google, I found a patch that helped on Linux to
get rid of the problem. I have applied that patch to our sources, and tested
them on my system successfully. Using the xorg.conf above and the mga-driver
starts a nice dual-headed system on which both screens are used for an extended
display (meaning the output is not mirrored :) ). I have created this
xsrc-specific patch, and would like to ask you to apply it to the repository,
so that everyone can benefit from this:
? xf86-video-mga.patch
Index: mga.h
===================================================================
RCS file: /cvsroot/xsrc/external/mit/xf86-video-mga/dist/src/mga.h,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 mga.h
--- mga.h 22 May 2010 10:09:00 -0000 1.1.1.4
+++ mga.h 9 May 2014 13:46:45 -0000
@@ -337,6 +337,10 @@
int mastervideoRam;
int slavevideoRam;
Bool directRenderingEnabled;
+ void * mappedIOBase;
+ int mappedIOUsage;
+ void * mappedILOADBase;
+ int mappedILOADUsage;
ScrnInfoPtr pScrn_1;
ScrnInfoPtr pScrn_2;
} MGAEntRec, *MGAEntPtr;
Index: mga_driver.c
===================================================================
RCS file: /cvsroot/xsrc/external/mit/xf86-video-mga/dist/src/mga_driver.c,v
retrieving revision 1.1.1.5
diff -u -r1.1.1.5 mga_driver.c
--- mga_driver.c 14 Aug 2010 08:33:53 -0000 1.1.1.5
+++ mga_driver.c 9 May 2014 13:46:45 -0000
@@ -2822,23 +2822,46 @@
if (!pMga->FBDev) {
#ifdef XSERVER_LIBPCIACCESS
- memory[pMga->io_bar] = &pMga->IOBase;
- memory[pMga->framebuffer_bar] = &pMga->FbBase;
+ pciaddr_t fbaddr = pMga->FbAddress;
+ pciaddr_t fbsize = pMga->FbMapSize;
+ err = pci_device_map_range(dev,
+ fbaddr, fbsize,
+ PCI_DEV_MAP_FLAG_WRITABLE,
+ (void **)&pMga->FbBase);
+ if (err) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Unable to map Framebuffer %08llX %llx. %s (%d)\n", (long
long)fbaddr, (long long)fbsize,
+ strerror(err), err);
+ return FALSE;
+ }
+ else
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "MAPPED Framebuffer %08llX %llx to %08llX.\n",
+ (long long)fbaddr, (long long)fbsize, (long
long)pMga->FbBase);
+
+ if(pMga->entityPrivate == NULL || pMga->entityPrivate->mappedIOUsage ==
0) {
+ region = &dev->regions[pMga->io_bar];
+ err = pci_device_map_range(dev,
+ region->base_addr, region->size,
+ PCI_DEV_MAP_FLAG_WRITABLE,
+ &pMga->IOBase);
+
+ if (err) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Unable to map IO Region %i. %s (%d)\n",
+ pMga->io_bar, strerror(err), err);
+ return FALSE;
+ }
- for (i = 0; i < 2; i++) {
- region = &dev->regions[i];
- err = pci_device_map_range(dev,
- region->base_addr, region->size,
- PCI_DEV_MAP_FLAG_WRITABLE,
- memory[i]);
+ if(pMga->entityPrivate != NULL) {
+ pMga->entityPrivate->mappedIOBase = pMga->IOBase;
+ }
+ }
+ else
+ pMga->IOBase = pMga->entityPrivate->mappedIOBase;
- if (err) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Unable to map BAR %i. %s (%d)\n",
- i, strerror(err), err);
- return FALSE;
- }
- }
+ if(pMga->entityPrivate != NULL)
+ pMga->entityPrivate->mappedIOUsage ++;
#else
/*
* For Alpha, we need to map SPARSE memory, since we need
@@ -2880,16 +2903,26 @@
if (pMga->iload_bar != -1) {
#ifdef XSERVER_LIBPCIACCESS
region = &dev->regions[pMga->iload_bar];
- err = pci_device_map_range(dev,
+ if(pMga->entityPrivate == NULL ||
pMga->entityPrivate->mappedILOADUsage == 0) {
+ err = pci_device_map_range(dev,
region->base_addr, region->size,
PCI_DEV_MAP_FLAG_WRITABLE,
(void *) &pMga->ILOADBase);
- if (err) {
+ if (err) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Unable to map BAR 2 (ILOAD region). %s (%d)\n",
strerror(err), err);
return FALSE;
+ }
+
+ if(pMga->entityPrivate != NULL)
+ pMga->entityPrivate->mappedILOADBase = pMga->ILOADBase;
}
+ else
+ pMga->ILOADBase = pMga->entityPrivate->mappedILOADBase;
+
+ if(pMga->entityPrivate != NULL)
+ pMga->entityPrivate->mappedILOADUsage ++;
#else
pMga->ILOADBase = xf86MapPciMem(pScrn->scrnIndex,
VIDMEM_MMIO | VIDMEM_MMIO_32BIT |
@@ -2919,10 +2952,19 @@
if (!pMga->FBDev) {
#ifdef XSERVER_LIBPCIACCESS
- pci_device_unmap_range(dev, pMga->IOBase,
- dev->regions[pMga->io_bar].size);
- pci_device_unmap_range(dev, pMga->FbBase,
- dev->regions[pMga->framebuffer_bar].size);
+ if(pMga->entityPrivate != NULL)
+ pMga->entityPrivate->mappedIOUsage --;
+ if(pMga->entityPrivate == NULL || pMga->entityPrivate->mappedIOUsage ==
0) {
+ pci_device_unmap_range(dev, pMga->IOBase,
+ dev->regions[pMga->io_bar].size);
+ if(pMga->entityPrivate != NULL)
+ pMga->entityPrivate->mappedIOBase = NULL;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "UNMAPPING framebuffer 0x%08llX,
0x%llX.\n",
+ (long long)pMga->FbBase, (long long)pMga->FbMapSize);
+
+ pci_device_unmap_range(dev, pMga->FbBase,
+ pMga->FbMapSize);
#else
xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pMga->IOBase, 0x4000);
xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pMga->FbBase,
pMga->FbMapSize);
@@ -2935,8 +2977,14 @@
if ((pMga->iload_bar != -1) && (pMga->ILOADBase != NULL)) {
#ifdef XSERVER_LIBPCIACCESS
- pci_device_unmap_range(dev, pMga->ILOADBase,
+ if(pMga->entityPrivate != NULL)
+ pMga->entityPrivate->mappedILOADUsage --;
+ if(pMga->entityPrivate == NULL || pMga->entityPrivate->mappedILOADUsage
== 0) {
+ pci_device_unmap_range(dev, pMga->ILOADBase,
dev->regions[pMga->iload_bar].size);
+ if(pMga->entityPrivate != NULL)
+ pMga->entityPrivate->mappedILOADBase = NULL;
+ }
#else
xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pMga->ILOADBase, 0x800000);
#endif
Home |
Main Index |
Thread Index |
Old Index