diff options
author | ldelgass <ldelgass> | 2003-02-26 09:49:51 +0000 |
---|---|---|
committer | ldelgass <ldelgass> | 2003-02-26 09:49:51 +0000 |
commit | ebce8f934a8bb868f6d390ec3b35a3dc2ae18c0b (patch) | |
tree | f18d7573b5f221774d3b7463eddc480f3aa3f4dd | |
parent | 1bc0e968047bbee8e50004db75241403adbf724d (diff) |
Add VBLANK sync/throttle support. Many code cleanups, including moving themach64-0-0-6-20030329-freeze
interrupt-related code in the DRM to the new mach64_irq.c.
17 files changed, 460 insertions, 331 deletions
diff --git a/xc/lib/GL/mesa/src/drv/mach64/mach64_context.h b/xc/lib/GL/mesa/src/drv/mach64/mach64_context.h index 97ef4356f..638870314 100644 --- a/xc/lib/GL/mesa/src/drv/mach64/mach64_context.h +++ b/xc/lib/GL/mesa/src/drv/mach64/mach64_context.h @@ -297,6 +297,10 @@ struct mach64_context { GLuint c_texsrc_card; GLuint c_vertexBuffers; #endif + + /* VBI + */ + GLuint vbl_seq; }; #define MACH64_CONTEXT(ctx) ((mach64ContextPtr)(ctx->DriverCtx)) diff --git a/xc/lib/GL/mesa/src/drv/mach64/mach64_ioctl.c b/xc/lib/GL/mesa/src/drv/mach64/mach64_ioctl.c index cfa71621a..1fbfbac45 100644 --- a/xc/lib/GL/mesa/src/drv/mach64/mach64_ioctl.c +++ b/xc/lib/GL/mesa/src/drv/mach64/mach64_ioctl.c @@ -260,6 +260,40 @@ static int mach64WaitForFrameCompletion( mach64ContextPtr mmesa ) return wait; } +static void mach64WaitForVBlank( mach64ContextPtr mmesa ) +{ + drmVBlank vbl; + int ret; + + if ( !mmesa->mach64Screen->irq ) + return; + + if ( getenv("LIBGL_SYNC_REFRESH") ) { + /* Wait until the next vertical blank */ + vbl.request.type = DRM_VBLANK_RELATIVE; + vbl.request.sequence = 1; + } else if ( getenv("LIBGL_THROTTLE_REFRESH") ) { + /* Wait for at least one vertical blank since the last call */ + vbl.request.type = DRM_VBLANK_ABSOLUTE; + vbl.request.sequence = mmesa->vbl_seq + 1; + } else { + return; + } + + UNLOCK_HARDWARE( mmesa ); + + if ((ret = drmWaitVBlank( mmesa->driFd, &vbl ))) { + fprintf(stderr, "%s: drmWaitVBlank returned %d, IRQs don't seem to be" + " working correctly.\nTry running with LIBGL_THROTTLE_REFRESH" + " and LIBL_SYNC_REFRESH unset.\n", __FUNCTION__, ret); + exit(1); + } + + mmesa->vbl_seq = vbl.reply.sequence; + + LOCK_HARDWARE( mmesa ); +} + /* Copy the back color buffer to the front color buffer. */ void mach64CopyBuffer( const __DRIdrawablePrivate *dPriv ) @@ -295,13 +329,14 @@ void mach64CopyBuffer( const __DRIdrawablePrivate *dPriv ) mmesa->hardwareWentIdle = 0; } - #if ENABLE_PERF_BOXES if ( mmesa->boxes ) { mach64PerformanceBoxesLocked( mmesa ); } #endif + mach64WaitForVBlank( mmesa ); + /* use front buffer cliprects */ nbox = dPriv->numClipRects; pbox = dPriv->pClipRects; diff --git a/xc/lib/GL/mesa/src/drv/mach64/mach64_screen.c b/xc/lib/GL/mesa/src/drv/mach64/mach64_screen.c index 4a9c3a233..2ed4b21ac 100644 --- a/xc/lib/GL/mesa/src/drv/mach64/mach64_screen.c +++ b/xc/lib/GL/mesa/src/drv/mach64/mach64_screen.c @@ -54,6 +54,22 @@ mach64CreateScreen( __DRIscreenPrivate *driScreen ) mach64Screen->IsPCI = serverInfo->IsPCI; + { + drmMach64GetParam gp; + int ret; + + gp.param = MACH64_PARAM_IRQ_NR; + gp.value = &mach64Screen->irq; + + ret = drmCommandWriteRead( driScreen->fd, DRM_MACH64_GETPARAM, + &gp, sizeof(gp)); + if (ret) { + fprintf(stderr, "DRM_MACH64_GETPARAM (MACH64_PARAM_IRQ_NR): %d\n", ret); + FREE( mach64Screen ); + return NULL; + } + } + mach64Screen->mmio.handle = serverInfo->regs; mach64Screen->mmio.size = serverInfo->regsSize; if ( drmMap( driScreen->fd, @@ -137,6 +153,9 @@ mach64DestroyScreen( __DRIscreenPrivate *driScreen ) { mach64ScreenRec *mach64Screen = (mach64ScreenRec *) driScreen->private; + if ( !mach64Screen ) + return; + if ( MACH64_DEBUG & DEBUG_VERBOSE_DRI ) fprintf( stderr, "mach64DestroyScreen\n" ); diff --git a/xc/lib/GL/mesa/src/drv/mach64/mach64_screen.h b/xc/lib/GL/mesa/src/drv/mach64/mach64_screen.h index fa453e0ba..ea0adb1c6 100644 --- a/xc/lib/GL/mesa/src/drv/mach64/mach64_screen.h +++ b/xc/lib/GL/mesa/src/drv/mach64/mach64_screen.h @@ -59,6 +59,7 @@ typedef struct { int IsPCI; int AGPMode; + unsigned int irq; /* IRQ number (0 means none) */ /* Shared Texture data */ int firstTexHeap, numTexHeaps; diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ati/atidri.c b/xc/programs/Xserver/hw/xfree86/drivers/ati/atidri.c index 34c7e301d..4068012bd 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/ati/atidri.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/ati/atidri.c @@ -978,6 +978,49 @@ static Bool ATIDRIMapBuffers( ScreenPtr pScreen ) return TRUE; } +static Bool ATIDRIIrqInit( ScreenPtr pScreen ) +{ + ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; + ATIPtr pATI = ATIPTR(pScreenInfo); + + if ( pATI->irq <= 0 ) { + pATI->irq = drmGetInterruptFromBusID(pATI->drmFD, + ((pciConfigPtr)pATI->PCIInfo + ->thisCard)->busnum, + ((pciConfigPtr)pATI->PCIInfo + ->thisCard)->devnum, + ((pciConfigPtr)pATI->PCIInfo + ->thisCard)->funcnum); + if ( pATI->irq <= 0 ) { + xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, + "[drm] Couldn't find IRQ for bus id %d:%d:%d\n", + ((pciConfigPtr)pATI->PCIInfo->thisCard)->busnum, + ((pciConfigPtr)pATI->PCIInfo->thisCard)->devnum, + ((pciConfigPtr)pATI->PCIInfo->thisCard)->funcnum); + pATI->irq = 0; + } else if ((drmCtlInstHandler(pATI->drmFD, pATI->irq)) != 0) { + xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, + "[drm] Failed to initialize interrupt handler with IRQ %d\n", + pATI->irq); + pATI->irq = 0; + } + + if (pATI->irq) + xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, + "[drm] Installed interrupt handler, using IRQ %d\n", + pATI->irq); + else { + xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, + "[drm] Falling back to irq-free operation\n", + pATI->irq); + return FALSE; + } + } + + return TRUE; + +} + /* Initialize the screen-specific data structures for the DRI and the * Rage Pro. This is the main entry point to the device-specific * initialization code. It calls device-independent DRI functions to @@ -1309,41 +1352,8 @@ Bool ATIDRIFinishScreenInit( ScreenPtr pScreen ) return FALSE; } -#if 0 - if ( pATI->irq <= 0 ) { - int ret; - pATI->irq = drmGetInterruptFromBusID(pATI->drmFD, - ((pciConfigPtr)pATI->PCIInfo - ->thisCard)->busnum, - ((pciConfigPtr)pATI->PCIInfo - ->thisCard)->devnum, - ((pciConfigPtr)pATI->PCIInfo - ->thisCard)->funcnum); - if ( pATI->irq <= 0 ) { - xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, - "[drm] Couldn't find IRQ for bus id %d:%d:%d\n", - ((pciConfigPtr)pATI->PCIInfo->thisCard)->busnum, - ((pciConfigPtr)pATI->PCIInfo->thisCard)->devnum, - ((pciConfigPtr)pATI->PCIInfo->thisCard)->funcnum); - pATI->irq = 0; - ATIDRICloseScreen(pScreen); - return FALSE; - } - ret = drmCtlInstHandler(pATI->drmFD, pATI->irq); - if ( ret < 0 ) { - xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, - "[drm] Cannot initialize interrupt handler with IRQ %d\n", - pATI->irq); - pATI->irq = 0; - ATIDRICloseScreen(pScreen); - return FALSE; - } - - xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, - "[drm] Installed interrupt handler, using IRQ %d\n", - pATI->irq); - } -#endif + /* Initialize IRQ */ + ATIDRIIrqInit( pScreen ); pSAREAPriv = (ATISAREAPrivPtr) DRIGetSAREAPrivate( pScreen ); memset( pSAREAPriv, 0, sizeof(*pSAREAPriv) ); @@ -1395,16 +1405,14 @@ void ATIDRICloseScreen( ScreenPtr pScreen ) /* Stop interrupt generation and handling if used */ if ( pATI->irq > 0 ) { - int ret; - ret = drmCtlUninstHandler(pATI->drmFD); - pATI->irq = 0; - if ( ret < 0 ) { + if ( drmCtlUninstHandler(pATI->drmFD) != 0 ) { xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, "[drm] Error uninstalling interrupt handler for IRQ %d\n", pATI->irq); } else { xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, "[drm] Uninstalled interrupt handler for IRQ %d\n", pATI->irq); } + pATI->irq = 0; } /* De-allocate DMA buffers */ diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ati/atilock.c b/xc/programs/Xserver/hw/xfree86/drivers/ati/atilock.c index 79dc6e16e..cf9d480fd 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/ati/atilock.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/ati/atilock.c @@ -117,6 +117,11 @@ ATIUnlock pATI->LockData.crtc_int_cntl = inr(CRTC_INT_CNTL); outr(CRTC_INT_CNTL, (pATI->LockData.crtc_int_cntl & ~CRTC_INT_ENS) | CRTC_INT_ACKS); +#ifdef XF86DRI + if (pATI->irq > 0) + outr(CRTC_INT_CNTL, (inr(CRTC_INT_CNTL) & ~CRTC_INT_ACKS) | + CRTC_VBLANK_INT_EN); /* Enable VBLANK interrupt - handled by DRM */ +#endif pATI->LockData.gen_test_cntl = inr(GEN_TEST_CNTL) & (GEN_OVR_OUTPUT_EN | GEN_OVR_POLARITY | GEN_CUR_EN | GEN_BLOCK_WR_EN); diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64.c b/xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64.c index e6a4ca71d..5d5335321 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64.c @@ -915,6 +915,7 @@ ATIMach64SetDPMSMode } #ifdef XF86DRI + /* XAA Sync requires the DRM lock if DRI enabled */ ATIDRILock(pScreenInfo); #endif @@ -2054,12 +2055,12 @@ ATIMach64LoadCursorImage CARD32 *pSrc = (pointer)pImage; volatile CARD32 *pDst = pATI->pCursorImage; - /* Synchronise video memory accesses */ - #ifdef XF86DRI + /* XAA Sync requires the DRM lock if DRI enabled */ ATIDRILock(pScreenInfo); #endif + /* Synchronise video memory accesses */ if (pXAAInfo && pXAAInfo->NeedToSync) (*pXAAInfo->Sync)(pScreenInfo); diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ati/mach64_common.h b/xc/programs/Xserver/hw/xfree86/drivers/ati/mach64_common.h index 190518bac..657b677fc 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/ati/mach64_common.h +++ b/xc/programs/Xserver/hw/xfree86/drivers/ati/mach64_common.h @@ -121,7 +121,8 @@ typedef struct { typedef struct { enum { - MACH64_PARAM_FRAMES_QUEUED = 0x01 + MACH64_PARAM_FRAMES_QUEUED = 0x01, + MACH64_PARAM_IRQ_NR = 0x02 } param; int *value; } drmMach64GetParam; diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Imakefile b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Imakefile index 0e2cd84f3..644cb9840 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Imakefile +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Imakefile @@ -23,6 +23,7 @@ LinkSourceFile(mach64.h,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(mach64_dma.c,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(mach64_drm.h,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(mach64_drv.h,$(XF86OSSRC)/shared/drm/kernel) +LinkSourceFile(mach64_irq.c,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(mach64_state.c,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(mga.h,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(mga_dma.c,$(XF86OSSRC)/shared/drm/kernel) diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.kernel b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.kernel index 829f85b2e..c738173d4 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.kernel +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.kernel @@ -7,12 +7,12 @@ list-multi := gamma.o tdfx.o r128.o mga.o i810.o i830.o ffb.o radeon.o mach64.o gamma-objs := gamma_drv.o gamma_dma.o tdfx-objs := tdfx_drv.o -mach64-objs := mach64_drv.o mach64_dma.o mach64_state.o -r128-objs := r128_drv.o r128_cce.o r128_state.o -mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o +mach64-objs := mach64_drv.o mach64_dma.o mach64_irq.o mach64_state.o +r128-objs := r128_drv.o r128_cce.o r128_irq.o r128_state.o +mga-objs := mga_drv.o mga_dma.o mga_irq.o mga_state.o mga_warp.o i810-objs := i810_drv.o i810_dma.o i830-objs := i830_drv.o i830_dma.o -radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o +radeon-objs := radeon_drv.o radeon_cp.o radeon_irq.o radeon_state.o ffb-objs := ffb_drv.o ffb_context.o obj-$(CONFIG_DRM_GAMMA) += gamma.o diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.linux b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.linux index a614a5cf4..2447af0ce 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.linux +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.linux @@ -58,7 +58,7 @@ R128HEADERS = r128.h r128_drv.h r128_drm.h $(DRMHEADERS) $(DRMTEMPLATES) RADEONOBJS = radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o RADEONHEADERS = radeon.h radeon_drv.h radeon_drm.h $(DRMHEADERS) \ $(DRMTEMPLATES) -MACH64OBJS= mach64_drv.o mach64_dma.o mach64_state.o +MACH64OBJS= mach64_drv.o mach64_dma.o mach64_irq.o mach64_state.o MACH64HEADERS= mach64.h mach64_drv.h mach64_drm.h $(DRMHEADERS) $(DRMTEMPLATES) INC = /usr/include diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64.h b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64.h index 86e155659..5993f13fd 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64.h @@ -2,6 +2,7 @@ * Created: Wed Feb 14 16:07:10 2001 by gareth@valinux.com * * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * Copyright 2002-2003 Leif Delgass * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,7 +19,7 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. @@ -70,94 +71,13 @@ [DRM_IOCTL_NR(DRM_IOCTL_MACH64_FLUSH)] = { mach64_dma_flush, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_MACH64_GETPARAM)] = { mach64_get_param, 1, 0 } - /* DMA customization: */ #define __HAVE_DMA 1 -#define __HAVE_DMA_FREELIST 0 - -#define MACH64_INTERRUPTS 0 - -#if MACH64_INTERRUPTS #define __HAVE_DMA_IRQ 1 -#define __HAVE_DMA_IRQ_BH 1 +#define __HAVE_VBL_IRQ 1 #define __HAVE_SHARED_IRQ 1 -/* called before installing service routine in _irq_install */ -#define DRIVER_PREINSTALL() \ -do { \ - u32 tmp; \ - drm_mach64_private_t *dev_priv = dev->dev_private; \ - \ - tmp = MACH64_READ(MACH64_CRTC_INT_CNTL); \ - DRM_DEBUG("Before PREINSTALL: CRTC_INT_CNTL = 0x%08x\n", tmp); \ - /* clear active interrupts */ \ - if ( tmp & (MACH64_CRTC_VBLANK_INT \ - | MACH64_CRTC_BUSMASTER_EOL_INT) ) { \ - /* ack bits are the same as active interrupt bits, */ \ - /* so write back tmp to clear active interrupts */ \ - MACH64_WRITE( MACH64_CRTC_INT_CNTL, tmp ); \ - } \ - \ - /* disable interrupts */ \ - tmp &= ~(MACH64_CRTC_VBLANK_INT_EN \ - | MACH64_CRTC_BUSMASTER_EOL_INT_EN); \ - MACH64_WRITE( MACH64_CRTC_INT_CNTL, tmp ); \ - DRM_DEBUG("After PREINSTALL: CRTC_INT_CNTL = 0x%08x\n", tmp); \ - \ -} while(0) - -/* called after installing service routine in _irq_install */ -#define DRIVER_POSTINSTALL() \ -do { \ - /* clear and enable interrupts */ \ - u32 tmp; \ - drm_mach64_private_t *dev_priv = dev->dev_private; \ - \ - tmp = MACH64_READ(MACH64_CRTC_INT_CNTL); \ - DRM_DEBUG("Before POSTINSTALL: CRTC_INT_CNTL = 0x%08x\n", tmp); \ - /* clear active interrupts */ \ - if ( tmp & (MACH64_CRTC_VBLANK_INT \ - | MACH64_CRTC_BUSMASTER_EOL_INT) ) { \ - /* ack bits are the same as active interrupt bits, */ \ - /* so write back tmp to clear active interrupts */ \ - MACH64_WRITE( MACH64_CRTC_INT_CNTL, tmp ); \ - } \ - \ - /* enable interrupts */ \ - tmp |= (MACH64_CRTC_VBLANK_INT_EN \ - | MACH64_CRTC_BUSMASTER_EOL_INT_EN); \ - MACH64_WRITE( MACH64_CRTC_INT_CNTL, tmp ); \ - DRM_DEBUG("After POSTINSTALL: CRTC_INT_CNTL = 0x%08x\n", tmp); \ - \ -} while(0) - -/* called before freeing irq in _irq_uninstall */ -#define DRIVER_UNINSTALL() \ -do { \ - u32 tmp; \ - drm_mach64_private_t *dev_priv = dev->dev_private; \ - if (dev_priv) { \ - tmp = MACH64_READ(MACH64_CRTC_INT_CNTL); \ - DRM_DEBUG("Before UNINSTALL: CRTC_INT_CNTL = 0x%08x\n", tmp); \ - /* clear active interrupts */ \ - if ( tmp & (MACH64_CRTC_VBLANK_INT \ - | MACH64_CRTC_BUSMASTER_EOL_INT) ) { \ - /* ack bits are the same as active interrupt bits, */ \ - /* so write back tmp to clear active interrupts */ \ - MACH64_WRITE( MACH64_CRTC_INT_CNTL, tmp ); \ - } \ - \ - /* disable interrupts */ \ - tmp &= ~(MACH64_CRTC_VBLANK_INT_EN \ - | MACH64_CRTC_BUSMASTER_EOL_INT_EN); \ - MACH64_WRITE( MACH64_CRTC_INT_CNTL, tmp ); \ - DRM_DEBUG("After UNINSTALL: CRTC_INT_CNTL = 0x%08x\n", tmp); \ - } \ -} while(0) - -#endif /* MACH64_INTERRUPTS */ - /* Buffer customization: */ diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64_dma.c b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64_dma.c index 39ac7897c..65274f1d9 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64_dma.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64_dma.c @@ -3,6 +3,7 @@ * * Copyright 2000 Gareth Hughes * Copyright 2002 Frank C. Earl + * Copyright 2002-2003 Leif Delgass * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -19,7 +20,7 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * THE COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * @@ -37,94 +38,6 @@ #include "mach64_drv.h" -#if MACH64_INTERRUPTS - -static DECLARE_WAIT_QUEUE_HEAD(read_wait); - - -/* ================================================================ - * Interrupt service routine and bottom half - currently unused - */ - -void mach64_dma_service(int irq, void *device, struct pt_regs *regs) -{ - drm_device_t *dev = (drm_device_t *) device; - drm_mach64_private_t *dev_priv = (drm_mach64_private_t *)dev->dev_private; - - unsigned int flags; - - /* Check to see if we've been interrupted for VBLANK or the BLIT completion - and ack the interrupt accordingly... Set flags for the handler to - know that it needs to process accordingly... */ - - flags = MACH64_READ(MACH64_CRTC_INT_CNTL); - if (flags & MACH64_CRTC_VBLANK_INT) - { - /* VBLANK -- GUI-master dispatch and polling... */ - MACH64_WRITE(MACH64_CRTC_INT_CNTL, flags | MACH64_CRTC_VBLANK_INT_AK); - atomic_inc(&dev_priv->intr_vblank); - } - if (flags & MACH64_CRTC_BUSMASTER_EOL_INT) - { - /* Completion of BM_SYSTEM_TABLE system bus master */ - MACH64_WRITE(MACH64_CRTC_INT_CNTL, flags | MACH64_CRTC_BUSMASTER_EOL_INT_AK); - atomic_inc(&dev_priv->intr_bm_complete); - } - /* Check for an error condition in the engine... */ - if (MACH64_READ(MACH64_FIFO_STAT) & 0x80000000) - { - /* This would be a failure to maintain FIFO discipline - per the SDK sources. Need to reset... */ - mach64_do_engine_reset(dev_priv); - } -#if 0 - /* According to reg. ref this bit is BUS_MSTR_RD_LINE and on my - * card (LT Pro), it's set by default (LLD) - */ - if (MACH64_READ(MACH64_BUS_CNTL) & 0x00200000) - { - /* This would be a host data error, per information from - Vernon Chiang @ ATI (Thanks, Vernon!). Need to reset... */ - mach64_do_engine_reset(dev_priv); - } -#endif - /* Ok, now that we've gotten that out of the way, schedule the bottom half accordingly... */ - queue_task(&dev->tq, &tq_immediate); - mark_bh(IMMEDIATE_BH); - - return; -} - -/* Bottom half - handle the interrupts acknowleded by the service routine */ -void mach64_dma_immediate_bh(void *device) -{ - drm_device_t *dev = (drm_device_t *) device; - drm_mach64_private_t *dev_priv = (drm_mach64_private_t *)dev->dev_private; - - /* Received system bus master completion interrupt */ - if (atomic_read(&dev_priv->intr_bm_complete) > 0) - { - atomic_set(&dev_priv->intr_bm_complete, 0); - - /* TODO: handler code */ - - } - - /* Received VBLANK interrupt */ - if (atomic_read(&dev_priv->intr_vblank) > 0) - { - atomic_set(&dev_priv->intr_vblank, 0); - - /* TODO: handler code */ - - } - - wake_up_interruptible(&read_wait); - return; -} - -#endif /* MACH64_INTERRUPTS */ - /* ================================================================ * Engine, FIFO control */ @@ -173,7 +86,7 @@ int mach64_wait_ring( drm_mach64_private_t *dev_priv, int n ) mach64_update_ring_snapshot( dev_priv ); if ( ring->space >= n ) { if (i > 0) { - DRM_DEBUG( "wait_ring: %d usecs\n", i ); + DRM_DEBUG( "%s: %d usecs\n", __FUNCTION__, i ); } return 0; } @@ -200,7 +113,7 @@ static int mach64_ring_idle( drm_mach64_private_t *dev_priv ) if ( ring->head == ring->tail && !(MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE) ) { if (i > 0) { - DRM_DEBUG( "mach64_ring_idle: %d usecs\n", i ); + DRM_DEBUG( "%s: %d usecs\n", __FUNCTION__, i ); } return 0; } @@ -248,7 +161,7 @@ int mach64_do_dma_idle( drm_mach64_private_t *dev_priv ) { /* wait for completion */ if ( (ret = mach64_ring_idle( dev_priv )) < 0 ) { - DRM_ERROR( "%s failed BM_GUI_TABLE=0x%08x tail: %d\n", __FUNCTION__, + DRM_ERROR( "%s failed BM_GUI_TABLE=0x%08x tail: %u\n", __FUNCTION__, MACH64_READ(MACH64_BM_GUI_TABLE), dev_priv->ring.tail ); return ret; } @@ -449,7 +362,7 @@ void mach64_dump_ring_info( drm_mach64_private_t *dev_priv ) DRM_INFO( "\n" ); DRM_INFO("ring contents:\n"); - DRM_INFO(" head_addr: 0x%08x head: %d tail: %d\n\n", + DRM_INFO(" head_addr: 0x%08x head: %u tail: %u\n\n", ring->head_addr, ring->head, ring->tail ); skipped = 0; @@ -729,19 +642,11 @@ static int mach64_do_dma_init( drm_device_t *dev, drm_mach64_init_t *init ) dev_priv->usec_timeout = 1000000; - /* Set up the freelist, placeholder list, pending list, and DMA request queue... */ + /* Set up the freelist, placeholder list and pending list */ INIT_LIST_HEAD(&dev_priv->free_list); INIT_LIST_HEAD(&dev_priv->placeholders); INIT_LIST_HEAD(&dev_priv->pending); -#if MACH64_INTERRUPTS - /* Set up for interrupt handling proper- clear state on the handler - * The handler is enabled by the DDX via the DRM(control) ioctl once we return - */ - atomic_set(&dev_priv->intr_vblank, 0); - atomic_set(&dev_priv->intr_bm_complete, 0); -#endif - DRM_GETSAREA(); if (!dev_priv->sarea) { @@ -898,8 +803,12 @@ static int mach64_do_dma_init( drm_device_t *dev, drm_mach64_init_t *init ) dev_priv->frame_ofs[i] = ~0; /* All ones indicates placeholder */ } - /* Set up the freelist, placeholder list, pending, and DMA request queues... */ - mach64_init_freelist( dev ); + /* Allocate the DMA buffer freelist */ + if ( (ret=mach64_init_freelist( dev )) ) { + DRM_ERROR("Freelist allocation failed\n"); + mach64_do_cleanup_dma( dev ); + return ret; + } return 0; } @@ -934,7 +843,7 @@ int mach64_do_dispatch_pseudo_dma( drm_mach64_private_t *dev_priv ) while ( ring->tail != ring->head ) { u32 buf_addr, new_target, offset; - int bytes, remaining, head, eol; + u32 bytes, remaining, head, eol; head = ring->head; @@ -968,7 +877,7 @@ int mach64_do_dispatch_pseudo_dma( drm_mach64_private_t *dev_priv ) } if (!found || buf == NULL) { - DRM_ERROR("Couldn't find pending buffer: head: %d tail: %d buf_addr: 0x%08x %s\n", + DRM_ERROR("Couldn't find pending buffer: head: %u tail: %u buf_addr: 0x%08x %s\n", head, ring->tail, buf_addr, (eol ? "eol" : "")); mach64_dump_ring_info( dev_priv ); mach64_do_engine_reset( dev_priv ); @@ -980,7 +889,7 @@ int mach64_do_dispatch_pseudo_dma( drm_mach64_private_t *dev_priv ) */ DRM_DEBUG("target: (0x%08x) %s\n", target, (target == MACH64_BM_HOSTDATA ? "BM_HOSTDATA" : "BM_ADDR")); - DRM_DEBUG("offset: %d bytes: %d used: %d\n", offset, bytes, buf->used); + DRM_DEBUG("offset: %u bytes: %u used: %u\n", offset, bytes, buf->used); remaining = (buf->used - offset) >> 2; /* dwords remaining in buffer */ used = bytes >> 2; /* dwords in buffer for this descriptor */ diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64_drm.h b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64_drm.h index 323fafd93..d3f3eb997 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64_drm.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64_drm.h @@ -3,6 +3,7 @@ * * Copyright 2000 Gareth Hughes * Copyright 2002 Frank C. Earl + * Copyright 2002-2003 Leif Delgass * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -19,7 +20,7 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * THE COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * @@ -169,7 +170,6 @@ typedef struct drm_mach64_sarea { #define DRM_IOCTL_MACH64_FLUSH DRM_IO( 0x47) #define DRM_IOCTL_MACH64_GETPARAM DRM_IOWR(0x48, drm_mach64_getparam_t) - /* Buffer flags for clears */ #define MACH64_FRONT 0x1 @@ -244,7 +244,8 @@ typedef struct drm_mach64_blit { typedef struct drm_mach64_getparam { enum { - MACH64_PARAM_FRAMES_QUEUED = 0x01 + MACH64_PARAM_FRAMES_QUEUED = 0x01, + MACH64_PARAM_IRQ_NR = 0x02 } param; int *value; } drm_mach64_getparam_t; diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64_drv.h index 9aa557399..748802508 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64_drv.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64_drv.h @@ -3,6 +3,7 @@ * * Copyright 2000 Gareth Hughes * Copyright 2002 Frank C. Earl + * Copyright 2002-2003 Leif Delgass * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -19,7 +20,7 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * THE COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * @@ -47,7 +48,7 @@ typedef struct drm_mach64_freelist { } drm_mach64_freelist_t; typedef struct drm_mach64_descriptor_ring { - dma_addr_t handle; + dma_addr_t handle; /* handle (bus address) of ring returned by pci_alloc_consistent() */ void *start; /* write pointer (cpu address) to start of descriptor ring */ u32 start_addr; /* bus address of beginning of descriptor ring */ int size; /* size of ring in bytes */ @@ -69,11 +70,6 @@ typedef struct drm_mach64_private { int usec_timeout; /* Number of microseconds to wait in the idle functions */ -#if MACH64_INTERRUPTS - atomic_t intr_vblank; /* Flag for the bottom half to know what to do */ - atomic_t intr_bm_complete; /* Flag for the bottom half to know what to do */ -#endif - /* DMA descriptor table (ring buffer) */ drm_mach64_descriptor_ring_t ring; int ring_running; @@ -373,25 +369,73 @@ extern int mach64_get_param( DRM_IOCTL_ARGS ); # define MACH64_CRTC_CRNT_VLINE_MASK 0x07ff0000 #define MACH64_CRTC_OFF_PITCH 0x0414 #define MACH64_CRTC_INT_CNTL 0x0418 +# define MACH64_CRTC_VBLANK (1 << 0) # define MACH64_CRTC_VBLANK_INT_EN (1 << 1) # define MACH64_CRTC_VBLANK_INT (1 << 2) -# define MACH64_CRTC_VBLANK_INT_AK (1 << 2) # define MACH64_CRTC_VLINE_INT_EN (1 << 3) # define MACH64_CRTC_VLINE_INT (1 << 4) -# define MACH64_CRTC_VLINE_INT_AK (1 << 4) -# define MACH64_CRTC_VLINE_SYNC (1 << 5) -# define MACH64_CRTC_FRAME (1 << 6) +# define MACH64_CRTC_VLINE_SYNC (1 << 5) /* 0=even, 1=odd */ +# define MACH64_CRTC_FRAME (1 << 6) /* 0=even, 1=odd */ # define MACH64_CRTC_SNAPSHOT_INT_EN (1 << 7) # define MACH64_CRTC_SNAPSHOT_INT (1 << 8) -# define MACH64_CRTC_SNAPSHOT_INT_AK (1 << 8) +# define MACH64_CRTC_I2C_INT_EN (1 << 9) +# define MACH64_CRTC_I2C_INT (1 << 10) +# define MACH64_CRTC2_VBLANK (1 << 11) /* LT Pro */ +# define MACH64_CRTC2_VBLANK_INT_EN (1 << 12) /* LT Pro */ +# define MACH64_CRTC2_VBLANK_INT (1 << 13) /* LT Pro */ +# define MACH64_CRTC2_VLINE_INT_EN (1 << 14) /* LT Pro */ +# define MACH64_CRTC2_VLINE_INT (1 << 15) /* LT Pro */ +# define MACH64_CRTC_CAPBUF0_INT_EN (1 << 16) +# define MACH64_CRTC_CAPBUF0_INT (1 << 17) +# define MACH64_CRTC_CAPBUF1_INT_EN (1 << 18) +# define MACH64_CRTC_CAPBUF1_INT (1 << 19) +# define MACH64_CRTC_OVERLAY_EOF_INT_EN (1 << 20) +# define MACH64_CRTC_OVERLAY_EOF_INT (1 << 21) +# define MACH64_CRTC_ONESHOT_CAP_INT_EN (1 << 22) +# define MACH64_CRTC_ONESHOT_CAP_INT (1 << 23) # define MACH64_CRTC_BUSMASTER_EOL_INT_EN (1 << 24) # define MACH64_CRTC_BUSMASTER_EOL_INT (1 << 25) -# define MACH64_CRTC_BUSMASTER_EOL_INT_AK (1 << 25) # define MACH64_CRTC_GP_INT_EN (1 << 26) # define MACH64_CRTC_GP_INT (1 << 27) -# define MACH64_CRTC_GP_INT_AK (1 << 27) +# define MACH64_CRTC2_VLINE_SYNC (1 << 28) /* LT Pro */ /* 0=even, 1=odd */ +# define MACH64_CRTC_SNAPSHOT2_INT_EN (1 << 29) /* LT Pro */ +# define MACH64_CRTC_SNAPSHOT2_INT (1 << 30) /* LT Pro */ # define MACH64_CRTC_VBLANK2_INT (1 << 31) -# define MACH64_CRTC_VBLANK2_INT_AK (1 << 31) +# define MACH64_CRTC_INT_ENS \ + ( \ + MACH64_CRTC_VBLANK_INT_EN | \ + MACH64_CRTC_VLINE_INT_EN | \ + MACH64_CRTC_SNAPSHOT_INT_EN | \ + MACH64_CRTC_I2C_INT_EN | \ + MACH64_CRTC2_VBLANK_INT_EN | \ + MACH64_CRTC2_VLINE_INT_EN | \ + MACH64_CRTC_CAPBUF0_INT_EN | \ + MACH64_CRTC_CAPBUF1_INT_EN | \ + MACH64_CRTC_OVERLAY_EOF_INT_EN | \ + MACH64_CRTC_ONESHOT_CAP_INT_EN | \ + MACH64_CRTC_BUSMASTER_EOL_INT_EN | \ + MACH64_CRTC_GP_INT_EN | \ + MACH64_CRTC_SNAPSHOT2_INT_EN | \ + 0 \ + ) +# define MACH64_CRTC_INT_ACKS \ + ( \ + MACH64_CRTC_VBLANK_INT | \ + MACH64_CRTC_VLINE_INT | \ + MACH64_CRTC_SNAPSHOT_INT | \ + MACH64_CRTC_I2C_INT | \ + MACH64_CRTC2_VBLANK_INT | \ + MACH64_CRTC2_VLINE_INT | \ + MACH64_CRTC_CAPBUF0_INT | \ + MACH64_CRTC_CAPBUF1_INT | \ + MACH64_CRTC_OVERLAY_EOF_INT | \ + MACH64_CRTC_ONESHOT_CAP_INT | \ + MACH64_CRTC_BUSMASTER_EOL_INT | \ + MACH64_CRTC_GP_INT | \ + MACH64_CRTC_SNAPSHOT2_INT | \ + MACH64_CRTC_VBLANK2_INT | \ + 0 \ + ) #define MACH64_DATATYPE_CI8 2 #define MACH64_DATATYPE_ARGB1555 3 @@ -428,10 +472,121 @@ extern int mach64_get_param( DRM_IOCTL_ARGS ); #define MMSELECT(r) (ISMMREG0(r) ? MMSELECT0(r) : MMSELECT1(r)) /* ================================================================ + * DMA constants + */ + +/* DMA descriptor field indices: + * The descriptor fields are loaded into the read-only + * BM_* system bus master registers during a bus-master operation + */ +#define MACH64_DMA_FRAME_BUF_OFFSET 0 /* BM_FRAME_BUF_OFFSET */ +#define MACH64_DMA_SYS_MEM_ADDR 1 /* BM_SYSTEM_MEM_ADDR */ +#define MACH64_DMA_COMMAND 2 /* BM_COMMAND */ +#define MACH64_DMA_RESERVED 3 /* BM_STATUS */ + +/* BM_COMMAND descriptor field flags */ +#define MACH64_DMA_HOLD_OFFSET (1<<30) /* Don't increment DMA_FRAME_BUF_OFFSET */ +#define MACH64_DMA_EOL (1<<31) /* End of descriptor list flag */ + +#define MACH64_DMA_CHUNKSIZE 0x1000 /* 4kB per DMA descriptor */ +#define MACH64_APERTURE_OFFSET 0x7ff800 /* frame-buffer offset for gui-masters */ + + +/* ================================================================ * Misc helper macros */ -static inline void mach64_ring_start( drm_mach64_private_t *dev_priv ) +static __inline__ void mach64_set_dma_eol( volatile u32 * addr ) +{ +#if defined(__i386__) + int nr = 31; + + /* Taken from include/asm-i386/bitops.h linux header */ + __asm__ __volatile__( "lock;" + "btsl %1,%0" + :"=m" (*addr) + :"Ir" (nr)); +#elif defined(__powerpc__) + u32 old; + u32 mask = cpu_to_le32( MACH64_DMA_EOL ); + + /* Taken from the include/asm-ppc/bitops.h linux header */ + __asm__ __volatile__("\n\ +1: lwarx %0,0,%3 \n\ + or %0,%0,%2 \n\ + stwcx. %0,0,%3 \n\ + bne- 1b" + : "=&r" (old), "=m" (*addr) + : "r" (mask), "r" (addr), "m" (*addr) + : "cc"); +#elif defined(__alpha__) + u32 temp; + u32 mask = MACH64_DMA_EOL; + + /* Taken from the include/asm-alpha/bitops.h linux header */ + __asm__ __volatile__( + "1: ldl_l %0,%3\n" + " bis %0,%2,%0\n" + " stl_c %0,%1\n" + " beq %0,2f\n" + ".subsection 2\n" + "2: br 1b\n" + ".previous" + :"=&r" (temp), "=m" (*addr) + :"Ir" (mask), "m" (*addr)); +#else + u32 mask = cpu_to_le32( MACH64_DMA_EOL ); + + *addr |= mask; +#endif +} + +static __inline__ void mach64_clear_dma_eol( volatile u32 * addr ) +{ +#if defined(__i386__) + int nr = 31; + + /* Taken from include/asm-i386/bitops.h linux header */ + __asm__ __volatile__( "lock;" + "btrl %1,%0" + :"=m" (*addr) + :"Ir" (nr)); +#elif defined(__powerpc__) + u32 old; + u32 mask = cpu_to_le32( MACH64_DMA_EOL ); + + /* Taken from the include/asm-ppc/bitops.h linux header */ + __asm__ __volatile__("\n\ +1: lwarx %0,0,%3 \n\ + andc %0,%0,%2 \n\ + stwcx. %0,0,%3 \n\ + bne- 1b" + : "=&r" (old), "=m" (*addr) + : "r" (mask), "r" (addr), "m" (*addr) + : "cc"); +#elif defined(__alpha__) + u32 temp; + u32 mask = ~MACH64_DMA_EOL; + + /* Taken from the include/asm-alpha/bitops.h linux header */ + __asm__ __volatile__( + "1: ldl_l %0,%3\n" + " and %0,%2,%0\n" + " stl_c %0,%1\n" + " beq %0,2f\n" + ".subsection 2\n" + "2: br 1b\n" + ".previous" + :"=&r" (temp), "=m" (*addr) + :"Ir" (mask), "m" (*addr)); +#else + u32 mask = cpu_to_le32( ~MACH64_DMA_EOL ); + + *addr &= mask; +#endif +} + +static __inline__ void mach64_ring_start( drm_mach64_private_t *dev_priv ) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; @@ -448,9 +603,8 @@ static inline void mach64_ring_start( drm_mach64_private_t *dev_priv ) MACH64_WRITE( MACH64_BUS_CNTL, ( MACH64_READ(MACH64_BUS_CNTL) & ~MACH64_BUS_MASTER_DIS ) | MACH64_BUS_EXT_REG_EN ); + mach64_do_wait_for_idle( dev_priv ); } - - mach64_do_wait_for_idle( dev_priv ); /* reset descriptor table ring head */ MACH64_WRITE( MACH64_BM_GUI_TABLE_CMD, @@ -459,7 +613,7 @@ static inline void mach64_ring_start( drm_mach64_private_t *dev_priv ) dev_priv->ring_running = 1; } -static inline void mach64_ring_resume( drm_mach64_private_t *dev_priv, +static __inline__ void mach64_ring_resume( drm_mach64_private_t *dev_priv, drm_mach64_descriptor_ring_t *ring ) { DRM_DEBUG( "%s: head_addr: 0x%08x head: %d tail: %d space: %d\n", @@ -493,7 +647,7 @@ static inline void mach64_ring_resume( drm_mach64_private_t *dev_priv, } } -static inline void mach64_ring_tick( drm_mach64_private_t *dev_priv, +static __inline__ void mach64_ring_tick( drm_mach64_private_t *dev_priv, drm_mach64_descriptor_ring_t *ring ) { DRM_DEBUG( "%s: head_addr: 0x%08x head: %d tail: %d space: %d\n", @@ -540,7 +694,7 @@ static inline void mach64_ring_tick( drm_mach64_private_t *dev_priv, } } -static inline void mach64_ring_stop( drm_mach64_private_t *dev_priv ) +static __inline__ void mach64_ring_stop( drm_mach64_private_t *dev_priv ) { DRM_DEBUG( "%s: head_addr: 0x%08x head: %d tail: %d space: %d\n", __FUNCTION__, @@ -559,7 +713,7 @@ static inline void mach64_ring_stop( drm_mach64_private_t *dev_priv ) dev_priv->ring_running = 0; } -static inline void +static __inline__ void mach64_update_ring_snapshot( drm_mach64_private_t *dev_priv ) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; @@ -606,25 +760,6 @@ do { \ __ring_space_done: \ } while (0) -/* ================================================================ - * DMA constants - */ - -/* DMA descriptor field indices: - * The descriptor fields are loaded into the read-only - * BM_* system bus master registers during a bus-master operation - */ -#define MACH64_DMA_FRAME_BUF_OFFSET 0 /* BM_FRAME_BUF_OFFSET */ -#define MACH64_DMA_SYS_MEM_ADDR 1 /* BM_SYSTEM_MEM_ADDR */ -#define MACH64_DMA_COMMAND 2 /* BM_COMMAND */ -#define MACH64_DMA_RESERVED 3 /* BM_STATUS */ - -/* BM_COMMAND descriptor field flags */ -#define MACH64_DMA_HOLD_OFFSET (1<<30) /* Don't increment DMA_FRAME_BUF_OFFSET */ -#define MACH64_DMA_EOL (1<<31) /* End of descriptor list flag */ - -#define MACH64_DMA_CHUNKSIZE 0x1000 /* 4kB per DMA descriptor */ -#define MACH64_APERTURE_OFFSET 0x7ff800 /* frame-buffer offset for gui-masters */ /* ================================================================ * DMA descriptor ring macros @@ -666,52 +801,6 @@ do { \ _ring_write &= _ring_mask; \ } while (0) - -static __inline__ void mach64_clear_dma_eol( volatile u32 * addr ) -{ -#if defined(__i386__) - int nr = 31; - - /* Taken from include/asm-i386/bitops.h linux header */ - __asm__ __volatile__( "lock;" - "btrl %1,%0" - :"=m" (*addr) - :"Ir" (nr)); -#elif defined(__powerpc__) - u32 old; - u32 mask = cpu_to_le32( MACH64_DMA_EOL ); - - /* Taken from the include/asm-ppc/bitops.h linux header */ - __asm__ __volatile__("\n\ -1: lwarx %0,0,%3 \n\ - andc %0,%0,%2 \n\ - stwcx. %0,0,%3 \n\ - bne- 1b" - : "=&r" (old), "=m" (*addr) - : "r" (mask), "r" (addr), "m" (*addr) - : "cc"); -#elif defined(__alpha__) - u32 temp; - u32 mask = ~MACH64_DMA_EOL; - - /* Taken from the include/asm-alpha/bitops.h linux header */ - __asm__ __volatile__( - "1: ldl_l %0,%3\n" - " and %0,%2,%0\n" - " stl_c %0,%1\n" - " beq %0,2f\n" - ".subsection 2\n" - "2: br 1b\n" - ".previous" - :"=&r" (temp), "=m" (*addr) - :"Ir" (mask), "m" (*addr)); -#else - u32 mask = cpu_to_le32( ~MACH64_DMA_EOL ); - - *addr &= mask; -#endif -} - #define ADVANCE_RING() \ do { \ if ( MACH64_VERBOSE ) { \ @@ -747,7 +836,7 @@ do { \ #define GETRINGOFFSET() (_entry->ring_ofs) -static inline int mach64_find_pending_buf_entry ( drm_mach64_private_t *dev_priv, +static __inline__ int mach64_find_pending_buf_entry ( drm_mach64_private_t *dev_priv, drm_mach64_freelist_t **entry, drm_buf_t *buf ) { diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64_irq.c b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64_irq.c new file mode 100644 index 000000000..cdac4efae --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64_irq.c @@ -0,0 +1,126 @@ +/* mach64_irq.c -- IRQ handling for ATI Mach64 -*- linux-c -*- + * Created: Tue Feb 25, 2003 by Leif Delgass, based on radeon_irq.c/r128_irq.c + * + * Copyright (C) The Weather Channel, Inc. 2002. + * Copyright 2003 Leif Delgass + * All Rights Reserved. + * + * The Weather Channel (TM) funded Tungsten Graphics to develop the + * initial release of the Radeon 8500 driver under the XFree86 license. + * This notice must be preserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Eric Anholt <anholt@FreeBSD.org> + * Leif Delgass <ldelgass@retinalburn.net> + */ + +#include "mach64.h" +#include "drmP.h" +#include "drm.h" +#include "mach64_drm.h" +#include "mach64_drv.h" + +void DRM(dma_service)( DRM_IRQ_ARGS ) +{ + drm_device_t *dev = (drm_device_t *) arg; + drm_mach64_private_t *dev_priv = + (drm_mach64_private_t *)dev->dev_private; + int status; + + status = MACH64_READ( MACH64_CRTC_INT_CNTL ); + + /* VBLANK interrupt */ + if (status & MACH64_CRTC_VBLANK_INT) { + /* Mask off all interrupt ack bits before setting the ack bit, since + * there may be other handlers outside the DRM. + * + * NOTE: On mach64, you need to keep the enable bits set when doing + * the ack, despite what the docs say about not acking and enabling + * in a single write. + */ + MACH64_WRITE( MACH64_CRTC_INT_CNTL, (status & ~MACH64_CRTC_INT_ACKS) + | MACH64_CRTC_VBLANK_INT ); + + atomic_inc(&dev->vbl_received); + DRM_WAKEUP(&dev->vbl_queue); + DRM(vbl_send_signals)( dev ); + } +} + +int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence) +{ + unsigned int cur_vblank; + int ret = 0; + + /* Assume that the user has missed the current sequence number + * by about a day rather than she wants to wait for years + * using vertical blanks... + */ + DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ, + ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) ) + - *sequence ) <= (1<<23) ) ); + + *sequence = cur_vblank; + + return ret; +} + +/* drm_dma.h hooks +*/ +void DRM(driver_irq_preinstall)( drm_device_t *dev ) { + drm_mach64_private_t *dev_priv = + (drm_mach64_private_t *)dev->dev_private; + u32 status = MACH64_READ( MACH64_CRTC_INT_CNTL ); + + DRM_DEBUG("before install CRTC_INT_CTNL: 0x%08x\n", status ); + + /* Disable and clear VBLANK interrupt */ + MACH64_WRITE( MACH64_CRTC_INT_CNTL, (status & ~MACH64_CRTC_VBLANK_INT_EN) + | MACH64_CRTC_VBLANK_INT ); +} + +void DRM(driver_irq_postinstall)( drm_device_t *dev ) { + drm_mach64_private_t *dev_priv = + (drm_mach64_private_t *)dev->dev_private; + + /* Turn on VBLANK interrupt */ + MACH64_WRITE( MACH64_CRTC_INT_CNTL, MACH64_READ( MACH64_CRTC_INT_CNTL ) + | MACH64_CRTC_VBLANK_INT_EN ); + + DRM_DEBUG("after install CRTC_INT_CTNL: 0x%08x\n", MACH64_READ( MACH64_CRTC_INT_CNTL )); + +} + +void DRM(driver_irq_uninstall)( drm_device_t *dev ) { + drm_mach64_private_t *dev_priv = + (drm_mach64_private_t *)dev->dev_private; + if ( dev_priv ) { + /* Disable and clear VBLANK interrupt */ + MACH64_WRITE( MACH64_CRTC_INT_CNTL, + (MACH64_READ( MACH64_CRTC_INT_CNTL ) & ~MACH64_CRTC_VBLANK_INT_EN) + | MACH64_CRTC_VBLANK_INT ); + + DRM_DEBUG("after uninstall CRTC_INT_CTNL: 0x%08x\n", + MACH64_READ( MACH64_CRTC_INT_CNTL )); + } +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64_state.c b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64_state.c index cad08cd80..a22697012 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64_state.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mach64_state.c @@ -2,6 +2,7 @@ * Created: Sun Dec 03 19:20:26 2000 by gareth@valinux.com * * Copyright 2000 Gareth Hughes + * Copyright 2002-2003 Leif Delgass * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,7 +19,7 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * THE COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * @@ -870,15 +871,23 @@ int mach64_get_param( DRM_IOCTL_ARGS ) DRM_DEBUG( "%s\n", __FUNCTION__ ); - LOCK_TEST_WITH_RETURN( dev ); + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } DRM_COPY_FROM_USER_IOCTL( param, (drm_mach64_getparam_t *)data, sizeof(param) ); switch ( param.param ) { case MACH64_PARAM_FRAMES_QUEUED: + /* Needs lock since it calls mach64_ring_tick() */ + LOCK_TEST_WITH_RETURN( dev ); value = mach64_do_get_frames_queued( dev_priv ); break; + case MACH64_PARAM_IRQ_NR: + value = dev->irq; + break; default: return DRM_ERR(EINVAL); } |