summaryrefslogtreecommitdiff
path: root/src
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 /src
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).
Diffstat (limited to 'src')
-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;