summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-core/Makefile.kernel8
-rw-r--r--linux/Makefile.kernel8
-rw-r--r--linux/Makefile.linux2
-rw-r--r--shared-core/mach64_dma.c123
-rw-r--r--shared-core/mach64_drm.h7
-rw-r--r--shared-core/mach64_drv.h265
-rw-r--r--shared-core/mach64_irq.c126
-rw-r--r--shared-core/mach64_state.c13
-rw-r--r--shared/mach64.h86
-rw-r--r--shared/mach64_dma.c123
-rw-r--r--shared/mach64_drm.h7
-rw-r--r--shared/mach64_drv.h265
-rw-r--r--shared/mach64_irq.c126
-rw-r--r--shared/mach64_state.c13
14 files changed, 680 insertions, 492 deletions
diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel
index 829f85b2..c738173d 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 829f85b2..c738173d 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 a614a5cf..2447af0c 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 39ac7897..65274f1d 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 323fafd9..d3f3eb99 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 9aa55739..74880250 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 00000000..cdac4efa
--- /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 cad08cd8..a2269701 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 86e15565..5993f13f 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 39ac7897..65274f1d 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 323fafd9..d3f3eb99 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 9aa55739..74880250 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 00000000..cdac4efa
--- /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 cad08cd8..a2269701 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);
}