diff options
author | Ian Romanick <idr@us.ibm.com> | 2005-07-25 23:14:50 +0000 |
---|---|---|
committer | Ian Romanick <idr@us.ibm.com> | 2005-07-25 23:14:50 +0000 |
commit | fdb59d2535d7d517a14f3d6489ba91f3dac3b99f (patch) | |
tree | 97355924269b0d5956094f7f73605665bf940f7f | |
parent | 6030e8206db010f65199cbf5d332d2b47cdb3580 (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.h | 25 | ||||
-rw-r--r-- | src/mga_bios.c | 43 | ||||
-rw-r--r-- | src/mga_dacG.c | 5 | ||||
-rw-r--r-- | src/mga_dri.c | 37 |
4 files changed, 92 insertions, 18 deletions
@@ -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; |