summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <idr@us.ibm.com>2005-07-25 23:14:50 +0000
committerIan Romanick <idr@us.ibm.com>2005-07-25 23:14:50 +0000
commitfdb59d2535d7d517a14f3d6489ba91f3dac3b99f (patch)
tree97355924269b0d5956094f7f73605665bf940f7f
parent6030e8206db010f65199cbf5d332d2b47cdb3580 (diff)
PInS data on later cards (G200 and later) contains information about the
physical bus used for the card. This allows accurate detection of PCI cards that use a PCI-to-PCI bridge with an AGP chip. Correctly disable DRI on PCI cards used with pre-3.2 DRM. Previously the test was performed based on PCI ID (see above for why this is wrong) and was done *before* the DRM version was known. Bug #3759: <https://bugs.freedesktop.org/show_bug.cgi?id=3759> Correctly determine the PLL reference frequency from the PInS data. Previously the wrong bit was tested. Blame the dumb programmer that used cut-and-paste (that would be me).
-rw-r--r--src/mga.h25
-rw-r--r--src/mga_bios.c43
-rw-r--r--src/mga_dacG.c5
-rw-r--r--src/mga_dri.c37
4 files changed, 92 insertions, 18 deletions
diff --git a/src/mga.h b/src/mga.h
index 46c4dbe..32ea21b 100644
--- a/src/mga.h
+++ b/src/mga.h
@@ -305,6 +305,26 @@ struct mga_VCO {
};
/**
+ * Host interface types that can be set by the card's BIOS.
+ */
+typedef enum {
+ MGA_HOST_UNKNOWN0 = 0, /**< Meaning unknown. */
+ MGA_HOST_UNKNOWN1 = 1, /**< Meaning unknown. */
+ MGA_HOST_UNKNOWN2 = 2, /**< Meaning unknown. */
+ MGA_HOST_HYBRID = 3, /**< AGP 4x for data xfers only. */
+
+ /**
+ * PCI interface. Either native or via a universal PCI-to-PCI bridge
+ * chip. The PCI G450 and PCI G550 cards are examples.
+ */
+ MGA_HOST_PCI = 4,
+
+ MGA_HOST_AGP_1x = 5, /**< AGP 1x capable. */
+ MGA_HOST_AGP_2x = 6, /**< AGP 2x capable. */
+ MGA_HOST_AGP_4x = 7 /**< AGP 4x capable. */
+} mga_host_t;
+
+/**
* Card information derrived from BIOS PInS data.
*/
struct mga_bios_values {
@@ -339,6 +359,11 @@ struct mga_bios_values {
* by a capability bit stored in the PInS data.
*/
Bool fast_bitblt;
+
+ /**
+ * Type of physical interface used for the card.
+ */
+ mga_host_t host_interface;
};
diff --git a/src/mga_bios.c b/src/mga_bios.c
index 05e5a4f..8afd1ec 100644
--- a/src/mga_bios.c
+++ b/src/mga_bios.c
@@ -58,6 +58,9 @@
#include "mga.h"
+#if defined(DEBUG)
+#define BIOS_DEBUG
+#endif
/**
* Read a little-endian, unaligned data value and return as 16-bit.
@@ -125,6 +128,9 @@ static void mga_initialize_bios_values( MGAPtr pMga,
bios->pll_ref_freq = 14318;
bios->mem_clock = 50000;
+
+ bios->host_interface = (pMga->Chipset == PCI_CHIP_MGA2164_AGP)
+ ? MGA_HOST_AGP_1x : MGA_HOST_PCI;
break;
case PCI_CHIP_MGA1064:
@@ -138,6 +144,7 @@ static void mga_initialize_bios_values( MGAPtr pMga,
bios->pll_ref_freq = 14318;
bios->mem_clock = 50000;
+ bios->host_interface = MGA_HOST_PCI;
break;
case PCI_CHIP_MGAG100_PCI:
@@ -151,6 +158,16 @@ static void mga_initialize_bios_values( MGAPtr pMga,
bios->pll_ref_freq = 27050;
bios->mem_clock = 50000;
+
+ if ( pMga->Chipset == PCI_CHIP_MGAG100 ) {
+ bios->host_interface = MGA_HOST_AGP_1x;
+ }
+ else if ( pMga->Chipset == PCI_CHIP_MGAG200 ) {
+ bios->host_interface = MGA_HOST_AGP_2x;
+ }
+ else {
+ bios->host_interface = MGA_HOST_PCI;
+ }
break;
case PCI_CHIP_MGAG400:
@@ -161,6 +178,7 @@ static void mga_initialize_bios_values( MGAPtr pMga,
bios->pll_ref_freq = 27050;
bios->mem_clock = 200000;
+ bios->host_interface = MGA_HOST_AGP_4x;
break;
case PCI_CHIP_MGAG550:
@@ -173,6 +191,7 @@ static void mga_initialize_bios_values( MGAPtr pMga,
bios->pll_ref_freq = 27050;
bios->mem_clock = 284000;
+ bios->host_interface = MGA_HOST_AGP_4x;
break;
}
}
@@ -263,7 +282,7 @@ static void mga_parse_bios_ver_3( struct mga_bios_values * bios,
bios->system.max_freq = maxdac;
}
- if ( (bios_data[52] & 0x01) != 0 ) {
+ if ( (bios_data[52] & 0x20) != 0 ) {
bios->pll_ref_freq = 14318;
}
}
@@ -294,6 +313,8 @@ static void mga_parse_bios_ver_4( struct mga_bios_values * bios,
bios->pll_ref_freq = 14318;
}
+ bios->host_interface = (bios_data[95] >> 3) & 0x07;
+
if ( bios_data[65] != 0xff ) {
const unsigned system_pll = bios_data[65] * 4 * 1000;
bios->mem_clock = system_pll;
@@ -365,6 +386,8 @@ static void mga_parse_bios_ver_5( struct mga_bios_values * bios,
if ( (bios_data[110] & 0x01) != 0 ) {
bios->pll_ref_freq = 14318;
}
+
+ bios->host_interface = (bios_data[113] >> 3) & 0x07;
}
@@ -383,6 +406,18 @@ Bool mga_read_and_process_bios( ScrnInfoPtr pScrn )
unsigned version;
unsigned pins_len;
const CARD8 * pins_data;
+#ifdef BIOS_DEBUG
+ static const char * const host_interface_strings[8] = {
+ "Reserved",
+ "Reserved",
+ "Reserved",
+ "Hybrid (AGP 4x on data transfers only)",
+ "PCI",
+ "AGP 1x",
+ "AGP 2x",
+ "AGP 4x"
+ };
+#endif
/* Initialize the stored BIOS data to some reasonable values for the
@@ -501,7 +536,7 @@ Bool mga_read_and_process_bios( ScrnInfoPtr pScrn )
case 5: mga_parse_bios_ver_5( & pMga->bios, pins_data ); break;
}
-#ifdef DEBUG
+#ifdef BIOS_DEBUG
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"system VCO = [%u, %u]\n",
pMga->bios.system.min_freq, pMga->bios.system.max_freq);
@@ -519,6 +554,10 @@ Bool mga_read_and_process_bios( ScrnInfoPtr pScrn )
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"%s fast bitblt\n",
(pMga->bios.fast_bitblt) ? "Has" : "Does not have");
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Host interface: %s (%u)\n",
+ host_interface_strings[ pMga->bios.host_interface ],
+ pMga->bios.host_interface);
#endif
return TRUE;
diff --git a/src/mga_dacG.c b/src/mga_dacG.c
index 3385636..728dd89 100644
--- a/src/mga_dacG.c
+++ b/src/mga_dacG.c
@@ -170,8 +170,9 @@ MGAGCalcClock ( ScrnInfoPtr pScrn, long f_out,
*s = 3;
#ifdef DEBUG
- ErrorF( "f_out_requ =%ld f_pll_real=%.1f f_vco=%.1f n=0x%x m=0x%x p=0x%x s=0x%x\n",
- f_out, f_pll, f_vco, *best_n, *best_m, *p, *s );
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "f_out_requ =%ld f_pll_real=%.1f f_vco=%.1f n=0x%x m=0x%x p=0x%x s=0x%x\n",
+ f_out, (f_vco / (*p + 1)), f_vco, *best_n, *best_m, *p, *s );
#endif
}
diff --git a/src/mga_dri.c b/src/mga_dri.c
index 25b8a8c..bcaf03e 100644
--- a/src/mga_dri.c
+++ b/src/mga_dri.c
@@ -592,6 +592,10 @@ static unsigned int mylog2( unsigned int n )
* \todo
* The sizes used for the primary DMA buffer and the bin size and count for
* the secondary DMA buffers should be configurable from the xorg.conf.
+ *
+ * \todo
+ * This routine should use \c mga_bios_values::host_interface to limit the
+ * AGP mode. It the card is PCI, \c MGARec::agpSize should be forced to 0.
*/
static Bool MGADRIBootstrapDMA(ScreenPtr pScreen)
{
@@ -977,22 +981,10 @@ Bool MGADRIScreenInit( ScreenPtr pScreen )
case PCI_CHIP_MGAG550:
case PCI_CHIP_MGAG400:
case PCI_CHIP_MGAG200:
- break;
case PCI_CHIP_MGAG200_PCI:
- /* PCI cards are supported if the DRM version is at least 3.2 and the
- * user has not explicitly disabled the new DMA init path (i.e., to
- * support old version of the client-side driver that don't use the
- * new features of the 3.2 DRM).
- */
- if ( (pMGADRIServer->drm_version_minor >= 2) && !pMga->useOldDmaInit ) {
- break;
- }
- /*FALLTHROUGH*/
+ break;
default:
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "[drm] Direct rendering only supported with G200/G400/G550 AGP. PCI cards\n"
- "[drm] (G450 and G200) are only supported with DRM version 3.2 or higher and\n"
- "[drm] a recent client-side driver.\n");
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] Direct rendering only supported with G200/G400/G450/G550.\n");
return FALSE;
}
@@ -1218,6 +1210,23 @@ Bool MGADRIScreenInit( ScreenPtr pScreen )
}
}
+ if ( (pMga->bios.host_interface == MGA_HOST_PCI) &&
+ ((pMGADRIServer->drm_version_minor < 2) || pMga->useOldDmaInit) ) {
+ /* PCI cards are supported if the DRM version is at least 3.2 and the
+ * user has not explicitly disabled the new DMA init path (i.e., to
+ * support old version of the client-side driver that don't use the
+ * new features of the 3.2 DRM).
+ */
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[drm] Direct rendering on PCI cards requires DRM version 3.2 or higher\n"
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[drm] and a recent client-side driver. Also make sure that 'OldDmaInit'\n"
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[drm] is not selected in xorg.conf.'\n");
+ return FALSE;
+ }
+
+
if ( !MGADRIBootstrapDMA( pScreen ) ) {
DRICloseScreen( pScreen );
return FALSE;