diff options
Diffstat (limited to 'src/mga_dri.c')
-rw-r--r-- | src/mga_dri.c | 462 |
1 files changed, 261 insertions, 201 deletions
diff --git a/src/mga_dri.c b/src/mga_dri.c index d919161..11f3f03 100644 --- a/src/mga_dri.c +++ b/src/mga_dri.c @@ -46,6 +46,7 @@ +#include <inttypes.h> #include "mga_bios.h" #include "mga_reg.h" #include "mga.h" @@ -589,220 +590,260 @@ 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 - * Add support for PCI cards. */ static Bool MGADRIBootstrapDMA(ScreenPtr pScreen) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - MGAPtr pMga = MGAPTR(pScrn); - MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo; - unsigned long mode; - unsigned int vendor, device; - int ret, count, i; - - if(pMga->agpSize < 12)pMga->agpSize = 12; - if(pMga->agpSize > 64)pMga->agpSize = 64; /* cap */ - - /* FIXME: Make these configurable... - */ - pMGADRIServer->agp.size = pMga->agpSize * 1024 * 1024; - - pMGADRIServer->warp.offset = 0; - pMGADRIServer->warp.size = MGA_WARP_UCODE_SIZE; - - pMGADRIServer->primary.offset = (pMGADRIServer->warp.offset + - pMGADRIServer->warp.size); - pMGADRIServer->primary.size = 1024 * 1024; - - pMGADRIServer->buffers.offset = (pMGADRIServer->primary.offset + - pMGADRIServer->primary.size); - pMGADRIServer->buffers.size = MGA_NUM_BUFFERS * MGA_BUFFER_SIZE; - - - pMGADRIServer->agpTextures.offset = (pMGADRIServer->buffers.offset + - pMGADRIServer->buffers.size); - - pMGADRIServer->agpTextures.size = pMGADRIServer->agp.size - - pMGADRIServer->agpTextures.offset; - - if ( drmAgpAcquire( pMga->drmFD ) < 0 ) { - xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not available\n" ); - return FALSE; - } + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + MGAPtr pMga = MGAPTR(pScrn); + MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo; + int ret; + int requested_agp_mode; + int count; - mode = drmAgpGetMode( pMga->drmFD ); /* Default mode */ - vendor = drmAgpVendorId( pMga->drmFD ); - device = drmAgpDeviceId( pMga->drmFD ); - - mode &= ~MGA_AGP_MODE_MASK; - switch ( pMga->agpMode ) { - case 4: - mode |= MGA_AGP_4X_MODE; - case 2: - mode |= MGA_AGP_2X_MODE; - case 1: - default: - mode |= MGA_AGP_1X_MODE; - } - xf86DrvMsg( pScreen->myNum, X_INFO, - "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n", - mode, vendor, device, - pMga->PciInfo->vendor, - pMga->PciInfo->chipType ); + if(pMga->agpSize < 12)pMga->agpSize = 12; + if(pMga->agpSize > 64)pMga->agpSize = 64; /* cap */ - if ( drmAgpEnable( pMga->drmFD, mode ) < 0 ) { - xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n" ); - drmAgpRelease( pMga->drmFD ); - return FALSE; - } - if ( pMga->Chipset == PCI_CHIP_MGAG200 ) { - switch ( pMga->agpMode ) { - case 2: - xf86DrvMsg( pScreen->myNum, X_INFO, - "[drm] Enabling AGP 2x PLL encoding\n" ); - OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_ENABLE ); - break; - - case 1: - default: - xf86DrvMsg( pScreen->myNum, X_INFO, - "[drm] Disabling AGP 2x PLL encoding\n" ); - OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_DISABLE ); - pMga->agpMode = 1; - break; - } - } + requested_agp_mode = 0; + switch ( pMga->agpMode ) { + case 4: + requested_agp_mode |= MGA_AGP_4X_MODE; + case 2: + requested_agp_mode |= MGA_AGP_2X_MODE; + case 1: + default: + requested_agp_mode |= MGA_AGP_1X_MODE; + } - ret = drmAgpAlloc( pMga->drmFD, pMGADRIServer->agp.size, - 0, NULL, &pMGADRIServer->agp.handle ); - if ( ret < 0 ) { - xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret ); - drmAgpRelease( pMga->drmFD ); - return FALSE; - } - xf86DrvMsg( pScreen->myNum, X_INFO, - "[agp] %d kB allocated with handle 0x%08lx\n", - pMGADRIServer->agp.size/1024, pMGADRIServer->agp.handle ); - if ( drmAgpBind( pMga->drmFD, pMGADRIServer->agp.handle, 0 ) < 0 ) { - xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Could not bind memory\n" ); - drmAgpFree( pMga->drmFD, pMGADRIServer->agp.handle ); - drmAgpRelease( pMga->drmFD ); - return FALSE; - } + if ( (pMGADRIServer->drm_version_minor >= 2) && !pMga->useOldDmaInit ) { + drm_mga_dma_bootstrap_t dma_bs; - /* WARP microcode space - */ - if ( drmAddMap( pMga->drmFD, - pMGADRIServer->warp.offset, - pMGADRIServer->warp.size, - DRM_AGP, DRM_READ_ONLY, - &pMGADRIServer->warp.handle ) < 0 ) { - xf86DrvMsg( pScreen->myNum, X_ERROR, - "[agp] Could not add WARP microcode mapping\n" ); - return FALSE; - } - xf86DrvMsg( pScreen->myNum, X_INFO, - "[agp] WARP microcode handle = 0x%08lx\n", - pMGADRIServer->warp.handle ); - /* Primary DMA space - */ - if ( drmAddMap( pMga->drmFD, - pMGADRIServer->primary.offset, - pMGADRIServer->primary.size, - DRM_AGP, DRM_READ_ONLY, - &pMGADRIServer->primary.handle ) < 0 ) { - xf86DrvMsg( pScreen->myNum, X_ERROR, - "[agp] Could not add primary DMA mapping\n" ); - return FALSE; - } - xf86DrvMsg( pScreen->myNum, X_INFO, - "[agp] Primary DMA handle = 0x%08lx\n", - pMGADRIServer->primary.handle ); + (void) memset( & dma_bs, 0, sizeof( dma_bs ) ); + dma_bs.primary_size = 1024 * 1024; + dma_bs.secondary_bin_count = MGA_NUM_BUFFERS; + dma_bs.secondary_bin_size = MGA_BUFFER_SIZE; + dma_bs.agp_size = pMga->agpSize; + dma_bs.agp_mode = (pMga->forcePciDma) ? 0 : requested_agp_mode; - /* DMA buffers - */ - if ( drmAddMap( pMga->drmFD, - pMGADRIServer->buffers.offset, - pMGADRIServer->buffers.size, - DRM_AGP, 0, - &pMGADRIServer->buffers.handle ) < 0 ) { - xf86DrvMsg( pScreen->myNum, X_ERROR, - "[agp] Could not add DMA buffers mapping\n" ); - return FALSE; - } - xf86DrvMsg( pScreen->myNum, X_INFO, - "[agp] DMA buffers handle = 0x%08lx\n", - pMGADRIServer->buffers.handle ); - - count = drmAddBufs( pMga->drmFD, - MGA_NUM_BUFFERS, MGA_BUFFER_SIZE, - DRM_AGP_BUFFER, pMGADRIServer->buffers.offset ); - if ( count <= 0 ) { - xf86DrvMsg( pScrn->scrnIndex, X_INFO, - "[drm] failure adding %d %d byte DMA buffers\n", - MGA_NUM_BUFFERS, MGA_BUFFER_SIZE ); - return FALSE; - } - xf86DrvMsg( pScreen->myNum, X_INFO, - "[drm] Added %d %d byte DMA buffers\n", - count, MGA_BUFFER_SIZE ); - - i = mylog2(pMGADRIServer->agpTextures.size / MGA_NR_TEX_REGIONS); - if(i < MGA_LOG_MIN_TEX_REGION_SIZE) - i = MGA_LOG_MIN_TEX_REGION_SIZE; - pMGADRIServer->agpTextures.size = (pMGADRIServer->agpTextures.size >> i) << i; + ret = drmCommandWriteRead( pMga->drmFD, DRM_MGA_DMA_BOOTSTRAP, + & dma_bs, sizeof( dma_bs ) ); + if ( ret ) { + xf86DrvMsg( pScreen->myNum, X_ERROR, "[drm] Could not boot-strap DMA (%d)\n", ret ); + return FALSE; + } - if ( drmAddMap( pMga->drmFD, - pMGADRIServer->agpTextures.offset, - pMGADRIServer->agpTextures.size, - DRM_AGP, 0, - &pMGADRIServer->agpTextures.handle ) < 0 ) { - xf86DrvMsg( pScreen->myNum, X_ERROR, - "[agp] Could not add agpTexture mapping\n" ); - return FALSE; - } + pMga->agpMode = dma_bs.agp_mode; + pMGADRIServer->agp.size = dma_bs.agp_size; - xf86DrvMsg( pScreen->myNum, X_INFO, - "[agp] agpTexture handle = 0x%08lx\n", - pMGADRIServer->agpTextures.handle ); - xf86DrvMsg( pScreen->myNum, X_INFO, - "[agp] agpTexture size: %d kb\n", pMGADRIServer->agpTextures.size/1024 ); + pMGADRIServer->agpTextures.handle = dma_bs.texture_handle; + pMGADRIServer->agpTextures.size = dma_bs.texture_size; + } + else { + unsigned long mode; + unsigned int vendor, device; + int i; - pMGADRIServer->registers.size = MGAIOMAPSIZE; - if ( drmAddMap( pMga->drmFD, - (drm_handle_t)pMga->IOAddress, - pMGADRIServer->registers.size, - DRM_REGISTERS, DRM_READ_ONLY, - &pMGADRIServer->registers.handle ) < 0 ) { - xf86DrvMsg( pScreen->myNum, X_ERROR, - "[drm] Could not add MMIO registers mapping\n" ); - return FALSE; - } - xf86DrvMsg( pScreen->myNum, X_INFO, - "[drm] Registers handle = 0x%08lx\n", - pMGADRIServer->registers.handle ); + if ( pMga->forcePciDma ) { + const char * const msg = (pMGADRIServer->drm_version_minor < 2) + ? "DRM version is too old (3.2 or later required)" + : "old DMA init path was requested"; - pMGADRIServer->status.size = SAREA_MAX; + xf86DrvMsg( pScreen->myNum, X_WARNING, + "[agp] Cannot force PCI DMA because %s\n", msg ); + } - if ( drmAddMap( pMga->drmFD, 0, pMGADRIServer->status.size, - DRM_SHM, DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL, - &pMGADRIServer->status.handle ) < 0 ) { - xf86DrvMsg( pScreen->myNum, X_ERROR, - "[drm] Could not add status page mapping\n" ); - return FALSE; - } - xf86DrvMsg( pScreen->myNum, X_INFO, - "[drm] Status handle = 0x%08lx\n", - pMGADRIServer->status.handle ); + if ( drmAgpAcquire( pMga->drmFD ) < 0 ) { + xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not available\n" ); + return FALSE; + } + + mode = drmAgpGetMode( pMga->drmFD ); /* Default mode */ + vendor = drmAgpVendorId( pMga->drmFD ); + device = drmAgpDeviceId( pMga->drmFD ); + + mode = (mode & ~MGA_AGP_MODE_MASK) | requested_agp_mode; + + xf86DrvMsg( pScreen->myNum, X_INFO, + "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n", + mode, vendor, device, + pMga->PciInfo->vendor, + pMga->PciInfo->chipType ); + + if ( drmAgpEnable( pMga->drmFD, mode ) < 0 ) { + xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n" ); + drmAgpRelease( pMga->drmFD ); + return FALSE; + } + + if ( pMga->Chipset == PCI_CHIP_MGAG200 ) { + switch ( pMga->agpMode ) { + case 2: + xf86DrvMsg( pScreen->myNum, X_INFO, + "[drm] Enabling AGP 2x PLL encoding\n" ); + OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_ENABLE ); + break; + + case 1: + default: + xf86DrvMsg( pScreen->myNum, X_INFO, + "[drm] Disabling AGP 2x PLL encoding\n" ); + OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_DISABLE ); + pMga->agpMode = 1; + break; + } + } + + pMGADRIServer->agp.size = pMga->agpSize * 1024 * 1024; + + pMGADRIServer->warp.offset = 0; + pMGADRIServer->warp.size = MGA_WARP_UCODE_SIZE; + + pMGADRIServer->primary.offset = (pMGADRIServer->warp.offset + + pMGADRIServer->warp.size); + pMGADRIServer->primary.size = 1024 * 1024; + + pMGADRIServer->buffers.offset = (pMGADRIServer->primary.offset + + pMGADRIServer->primary.size); + pMGADRIServer->buffers.size = MGA_NUM_BUFFERS * MGA_BUFFER_SIZE; + + + pMGADRIServer->agpTextures.offset = (pMGADRIServer->buffers.offset + + pMGADRIServer->buffers.size); + + pMGADRIServer->agpTextures.size = (pMGADRIServer->agp.size - + pMGADRIServer->agpTextures.offset); + + ret = drmAgpAlloc( pMga->drmFD, pMGADRIServer->agp.size, + 0, NULL, &pMGADRIServer->agp.handle ); + if ( ret < 0 ) { + xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret ); + drmAgpRelease( pMga->drmFD ); + return FALSE; + } + xf86DrvMsg( pScreen->myNum, X_INFO, + "[agp] %d kB allocated with handle 0x%08lx\n", + pMGADRIServer->agp.size/1024, pMGADRIServer->agp.handle ); + + if ( drmAgpBind( pMga->drmFD, pMGADRIServer->agp.handle, 0 ) < 0 ) { + xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Could not bind memory\n" ); + drmAgpFree( pMga->drmFD, pMGADRIServer->agp.handle ); + drmAgpRelease( pMga->drmFD ); + return FALSE; + } + + /* WARP microcode space + */ + if ( drmAddMap( pMga->drmFD, + pMGADRIServer->warp.offset, + pMGADRIServer->warp.size, + DRM_AGP, DRM_READ_ONLY, + &pMGADRIServer->warp.handle ) < 0 ) { + xf86DrvMsg( pScreen->myNum, X_ERROR, + "[agp] Could not add WARP microcode mapping\n" ); + return FALSE; + } + xf86DrvMsg( pScreen->myNum, X_INFO, + "[agp] WARP microcode handle = 0x%08lx\n", + pMGADRIServer->warp.handle ); + + /* Primary DMA space + */ + if ( drmAddMap( pMga->drmFD, + pMGADRIServer->primary.offset, + pMGADRIServer->primary.size, + DRM_AGP, DRM_READ_ONLY, + &pMGADRIServer->primary.handle ) < 0 ) { + xf86DrvMsg( pScreen->myNum, X_ERROR, + "[agp] Could not add primary DMA mapping\n" ); + return FALSE; + } + xf86DrvMsg( pScreen->myNum, X_INFO, + "[agp] Primary DMA handle = 0x%08lx\n", + pMGADRIServer->primary.handle ); + + /* DMA buffers + */ + if ( drmAddMap( pMga->drmFD, + pMGADRIServer->buffers.offset, + pMGADRIServer->buffers.size, + DRM_AGP, 0, + &pMGADRIServer->buffers.handle ) < 0 ) { + xf86DrvMsg( pScreen->myNum, X_ERROR, + "[agp] Could not add DMA buffers mapping\n" ); + return FALSE; + } + xf86DrvMsg( pScreen->myNum, X_INFO, + "[agp] DMA buffers handle = 0x%08lx\n", + pMGADRIServer->buffers.handle ); + + count = drmAddBufs( pMga->drmFD, + MGA_NUM_BUFFERS, MGA_BUFFER_SIZE, + DRM_AGP_BUFFER, pMGADRIServer->buffers.offset ); + if ( count <= 0 ) { + xf86DrvMsg( pScrn->scrnIndex, X_INFO, + "[drm] failure adding %d %d byte DMA buffers\n", + MGA_NUM_BUFFERS, MGA_BUFFER_SIZE ); + return FALSE; + } + xf86DrvMsg( pScreen->myNum, X_INFO, + "[drm] Added %d %d byte DMA buffers\n", + count, MGA_BUFFER_SIZE ); + + i = mylog2(pMGADRIServer->agpTextures.size / MGA_NR_TEX_REGIONS); + if(i < MGA_LOG_MIN_TEX_REGION_SIZE) + i = MGA_LOG_MIN_TEX_REGION_SIZE; + pMGADRIServer->agpTextures.size = (pMGADRIServer->agpTextures.size >> i) << i; + + if ( drmAddMap( pMga->drmFD, + pMGADRIServer->agpTextures.offset, + pMGADRIServer->agpTextures.size, + DRM_AGP, 0, + &pMGADRIServer->agpTextures.handle ) < 0 ) { + xf86DrvMsg( pScreen->myNum, X_ERROR, + "[agp] Could not add agpTexture mapping\n" ); + return FALSE; + } + + xf86DrvMsg( pScreen->myNum, X_INFO, + "[agp] agpTexture handle = 0x%08lx\n", + pMGADRIServer->agpTextures.handle ); + xf86DrvMsg( pScreen->myNum, X_INFO, + "[agp] agpTexture size: %d kb\n", pMGADRIServer->agpTextures.size/1024 ); + + pMGADRIServer->registers.size = MGAIOMAPSIZE; + + if ( drmAddMap( pMga->drmFD, + (drm_handle_t)pMga->IOAddress, + pMGADRIServer->registers.size, + DRM_REGISTERS, DRM_READ_ONLY, + &pMGADRIServer->registers.handle ) < 0 ) { + xf86DrvMsg( pScreen->myNum, X_ERROR, + "[drm] Could not add MMIO registers mapping\n" ); + return FALSE; + } + xf86DrvMsg( pScreen->myNum, X_INFO, + "[drm] Registers handle = 0x%08lx\n", + pMGADRIServer->registers.handle ); + + pMGADRIServer->status.size = SAREA_MAX; + + if ( drmAddMap( pMga->drmFD, 0, pMGADRIServer->status.size, + DRM_SHM, DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL, + &pMGADRIServer->status.handle ) < 0 ) { + xf86DrvMsg( pScreen->myNum, X_ERROR, + "[drm] Could not add status page mapping\n" ); + return FALSE; + } + xf86DrvMsg( pScreen->myNum, X_INFO, + "[drm] Status handle = 0x%08lx\n", + pMGADRIServer->status.handle ); + } - return TRUE; + return TRUE; } static Bool MGADRIKernelInit( ScreenPtr pScreen ) @@ -934,13 +975,23 @@ Bool MGADRIScreenInit( ScreenPtr pScreen ) case PCI_CHIP_MGAG550: case PCI_CHIP_MGAG400: case PCI_CHIP_MGAG200: -#if 0 + break; case PCI_CHIP_MGAG200_PCI: -#endif - break; + /* 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*/ default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] Direct rendering only supported with G200/G400/G550 AGP\n"); - return FALSE; + 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"); + return FALSE; } /* Check that the GLX, DRI, and DRM modules have been loaded by testing @@ -1158,6 +1209,9 @@ Bool MGADRIScreenInit( ScreenPtr pScreen ) MGADRICloseScreen( pScreen ); /* FIXME: ??? */ return FALSE; } + pMGADRIServer->drm_version_major = version->version_major; + pMGADRIServer->drm_version_minor = version->version_minor; + drmFreeVersion( version ); } } @@ -1252,11 +1306,17 @@ Bool MGADRIFinishScreenInit( ScreenPtr pScreen ) pMGADRI->agpTextureOffset = (unsigned int)pMGADRIServer->agpTextures.handle; pMGADRI->agpTextureSize = (unsigned int)pMGADRIServer->agpTextures.size; + pMGADRI->sarea_priv_offset = sizeof(XF86DRISAREARec); + + + /* Newer versions of the client-side driver do not need these if the + * kernel version is high enough to support interrupt based waiting. + */ + pMGADRI->registers.handle = pMGADRIServer->registers.handle; pMGADRI->registers.size = pMGADRIServer->registers.size; pMGADRI->primary.handle = pMGADRIServer->primary.handle; pMGADRI->primary.size = pMGADRIServer->primary.size; - pMGADRI->sarea_priv_offset = sizeof(XF86DRISAREARec); /* These are no longer used by the client-side DRI driver. They should |