diff options
author | Leif Delgass <ldelgass@users.sourceforge.net> | 2003-02-26 09:49:54 +0000 |
---|---|---|
committer | Leif Delgass <ldelgass@users.sourceforge.net> | 2003-02-26 09:49:54 +0000 |
commit | ae0b8f750ae4ee190f7567fee5aca95d92e7895e (patch) | |
tree | d84c6248f4765a932b9e41aadf3e78fba5a207e8 | |
parent | 3cde41f7cd7f439c11e845fd379e62a45611aa40 (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.
-rw-r--r-- | linux-core/Makefile.kernel | 8 | ||||
-rw-r--r-- | linux/Makefile.kernel | 8 | ||||
-rw-r--r-- | linux/Makefile.linux | 2 | ||||
-rw-r--r-- | shared-core/mach64_dma.c | 123 | ||||
-rw-r--r-- | shared-core/mach64_drm.h | 7 | ||||
-rw-r--r-- | shared-core/mach64_drv.h | 265 | ||||
-rw-r--r-- | shared-core/mach64_irq.c | 126 | ||||
-rw-r--r-- | shared-core/mach64_state.c | 13 | ||||
-rw-r--r-- | shared/mach64.h | 86 | ||||
-rw-r--r-- | shared/mach64_dma.c | 123 | ||||
-rw-r--r-- | shared/mach64_drm.h | 7 | ||||
-rw-r--r-- | shared/mach64_drv.h | 265 | ||||
-rw-r--r-- | shared/mach64_irq.c | 126 | ||||
-rw-r--r-- | shared/mach64_state.c | 13 |
14 files changed, 680 insertions, 492 deletions
diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index 829f85b2e..c738173d4 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/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/linux/Makefile.kernel b/linux/Makefile.kernel index 829f85b2e..c738173d4 100644 --- a/linux/Makefile.kernel +++ b/linux/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/linux/Makefile.linux b/linux/Makefile.linux index a614a5cf4..2447af0ce 100644 --- a/linux/Makefile.linux +++ b/linux/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/shared-core/mach64_dma.c b/shared-core/mach64_dma.c index 39ac7897c..65274f1d9 100644 --- a/shared-core/mach64_dma.c +++ b/shared-core/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/shared-core/mach64_drm.h b/shared-core/mach64_drm.h index 323fafd93..d3f3eb997 100644 --- a/shared-core/mach64_drm.h +++ b/shared-core/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/shared-core/mach64_drv.h b/shared-core/mach64_drv.h index 9aa557399..748802508 100644 --- a/shared-core/mach64_drv.h +++ b/shared-core/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/shared-core/mach64_irq.c b/shared-core/mach64_irq.c new file mode 100644 index 000000000..cdac4efae --- /dev/null +++ b/shared-core/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/shared-core/mach64_state.c b/shared-core/mach64_state.c index cad08cd80..a22697012 100644 --- a/shared-core/mach64_state.c +++ b/shared-core/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); } diff --git a/shared/mach64.h b/shared/mach64.h index 86e155659..5993f13fd 100644 --- a/shared/mach64.h +++ b/shared/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/shared/mach64_dma.c b/shared/mach64_dma.c index 39ac7897c..65274f1d9 100644 --- a/shared/mach64_dma.c +++ b/shared/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/shared/mach64_drm.h b/shared/mach64_drm.h index 323fafd93..d3f3eb997 100644 --- a/shared/mach64_drm.h +++ b/shared/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/shared/mach64_drv.h b/shared/mach64_drv.h index 9aa557399..748802508 100644 --- a/shared/mach64_drv.h +++ b/shared/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/shared/mach64_irq.c b/shared/mach64_irq.c new file mode 100644 index 000000000..cdac4efae --- /dev/null +++ b/shared/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/shared/mach64_state.c b/shared/mach64_state.c index cad08cd80..a22697012 100644 --- a/shared/mach64_state.c +++ b/shared/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); } |