summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2002-08-26 20:02:26 +0000
committerKeith Whitwell <keith@tungstengraphics.com>2002-08-26 20:02:26 +0000
commitc3d2e90cc79c1b942e184c2dfb708965b38bb344 (patch)
tree846393b13f57e987a9085302901e7568e731a1a4
parentc9d387a04851a543dcb0e683dd17006752a07fc3 (diff)
merged trunk into branchr200-0-1-20020822
-rw-r--r--bsd-core/drm_drv.c74
-rw-r--r--bsd-core/drm_os_freebsd.h21
-rw-r--r--bsd/drm_drv.h74
-rw-r--r--bsd/drm_os_freebsd.h21
-rw-r--r--linux-core/drmP.h2
-rw-r--r--linux-core/drm_agpsupport.c4
-rw-r--r--linux-core/drm_drv.c18
-rw-r--r--linux-core/drm_stub.c4
-rw-r--r--linux-core/drm_vm.c32
-rw-r--r--linux-core/i810_dma.c27
-rw-r--r--linux-core/i830_dma.c24
-rw-r--r--linux/Makefile.linux4
-rw-r--r--linux/drmP.h2
-rw-r--r--linux/drm_agpsupport.h4
-rw-r--r--linux/drm_drv.h18
-rw-r--r--linux/drm_stub.h4
-rw-r--r--linux/drm_vm.h32
-rw-r--r--linux/i810_dma.c27
-rw-r--r--linux/i830_dma.c24
-rw-r--r--shared-core/mga_drv.h2
-rw-r--r--shared-core/mga_state.c1
-rw-r--r--shared-core/radeon_cp.c22
-rw-r--r--shared-core/radeon_drv.h5
-rw-r--r--shared-core/radeon_state.c20
-rw-r--r--shared/mga_drv.h2
-rw-r--r--shared/mga_state.c1
-rw-r--r--shared/radeon_cp.c22
-rw-r--r--shared/radeon_drv.h5
-rw-r--r--shared/radeon_state.c20
29 files changed, 358 insertions, 158 deletions
diff --git a/bsd-core/drm_drv.c b/bsd-core/drm_drv.c
index 45e145dc..81ca644a 100644
--- a/bsd-core/drm_drv.c
+++ b/bsd-core/drm_drv.c
@@ -1221,27 +1221,83 @@ int DRM(unlock)( DRM_IOCTL_ARGS )
}
#if DRM_LINUX
+#define LINUX_IOCTL_DRM_MIN 0x6400
+#define LINUX_IOCTL_DRM_MAX 0x64ff
+
static linux_ioctl_function_t DRM( linux_ioctl);
static struct linux_ioctl_handler DRM( handler) = {DRM( linux_ioctl), LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX};
SYSINIT (DRM( register), SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_register_handler, &DRM( handler));
SYSUNINIT(DRM( unregister), SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_unregister_handler, &DRM( handler));
+#define LINUX_IOC_VOID IOC_VOID
+#define LINUX_IOC_IN IOC_OUT /* Linux has the values the other way around */
+#define LINUX_IOC_OUT IOC_IN
+
/*
* Linux emulation IOCTL
*/
static int
DRM(linux_ioctl)(DRM_STRUCTPROC *p, struct linux_ioctl_args* args)
{
+ u_long cmd = args->cmd;
+#define STK_PARAMS 128
+ union {
+ char stkbuf[STK_PARAMS];
+ long align;
+ } ubuf;
+ caddr_t data=NULL, memp=NULL;
+ u_int size = IOCPARM_LEN(cmd);
+ int error;
#if (__FreeBSD_version >= 500000)
- struct file *fp = p->td_proc->p_fd->fd_ofiles[args->fd];
+ struct file *fp;
#else
- struct file *fp = p->p_fd->fd_ofiles[args->fd];
-#endif
- u_long cmd = args->cmd;
- caddr_t data = (caddr_t) args->arg;
- /*
- * Pass the ioctl off to our standard handler.
- */
- return(fo_ioctl(fp, cmd, data, p));
+ struct file *fp = p->p_fd->fd_ofiles[args->fd];
+#endif
+ if ( size > STK_PARAMS ) {
+ if ( size > IOCPARM_MAX )
+ return EINVAL;
+ memp = malloc( (u_long)size, DRM(M_DRM), M_WAITOK );
+ data = memp;
+ } else {
+ data = ubuf.stkbuf;
+ }
+
+ if ( cmd & LINUX_IOC_IN ) {
+ if ( size ) {
+ error = copyin( (caddr_t)args->arg, data, (u_int)size );
+ if (error) {
+ if ( memp )
+ free( data, DRM(M_DRM) );
+ return error;
+ }
+ } else {
+ data = (caddr_t)args->arg;
+ }
+ } else if ( (cmd & LINUX_IOC_OUT) && size ) {
+ /*
+ * Zero the buffer so the user always
+ * gets back something deterministic.
+ */
+ bzero( data, size );
+ } else if ( cmd & LINUX_IOC_VOID ) {
+ *(caddr_t *)data = (caddr_t)args->arg;
+ }
+
+#if (__FreeBSD_version >= 500000)
+ if ( (error = fget( p, args->fd, &fp )) != 0 ) {
+ if ( memp )
+ free( memp, DRM(M_DRM) );
+ return (error);
+ }
+ error = fo_ioctl( fp, cmd, data, p->td_ucred, p );
+ fdrop( fp, p );
+#else
+ error = fo_ioctl( fp, cmd, data, p );
+#endif
+ if ( error == 0 && (cmd & LINUX_IOC_OUT) && size )
+ error = copyout( data, (caddr_t)args->arg, (u_int)size );
+ if ( memp )
+ free( memp, DRM(M_DRM) );
+ return error;
}
#endif /* DRM_LINUX */
diff --git a/bsd-core/drm_os_freebsd.h b/bsd-core/drm_os_freebsd.h
index 23838139..6f878d4f 100644
--- a/bsd-core/drm_os_freebsd.h
+++ b/bsd-core/drm_os_freebsd.h
@@ -65,7 +65,6 @@
#include <sys/proc.h>
#include <machine/../linux/linux.h>
#include <machine/../linux/linux_proto.h>
-#include "drm_linux.h"
#endif
#define DRM_TIME_SLICE (hz/20) /* Time slice for GLXContexts */
@@ -140,14 +139,18 @@ do { \
} \
} while (0)
-#define DRM_COPY_TO_USER_IOCTL(arg1, arg2, arg3) \
- *arg1 = arg2
-#define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \
- arg1 = *arg2
-#define DRM_COPY_TO_USER(arg1, arg2, arg3) \
- copyout(arg2, arg1, arg3)
-#define DRM_COPY_FROM_USER(arg1, arg2, arg3) \
- copyin(arg2, arg1, arg3)
+#define DRM_COPY_TO_USER_IOCTL(user, kern, size) \
+ if ( IOCPARM_LEN(cmd) != size) \
+ return EINVAL; \
+ *user = kern;
+#define DRM_COPY_FROM_USER_IOCTL(kern, user, size) \
+ if ( IOCPARM_LEN(cmd) != size) \
+ return EINVAL; \
+ kern = *user;
+#define DRM_COPY_TO_USER(user, kern, size) \
+ copyout(kern, user, size)
+#define DRM_COPY_FROM_USER(kern, user, size) \
+ copyin(user, kern, size)
/* Macros for userspace access with checking readability once */
/* FIXME: can't find equivalent functionality for nocheck yet.
* It's be slower than linux, but should be correct.
diff --git a/bsd/drm_drv.h b/bsd/drm_drv.h
index 45e145dc..81ca644a 100644
--- a/bsd/drm_drv.h
+++ b/bsd/drm_drv.h
@@ -1221,27 +1221,83 @@ int DRM(unlock)( DRM_IOCTL_ARGS )
}
#if DRM_LINUX
+#define LINUX_IOCTL_DRM_MIN 0x6400
+#define LINUX_IOCTL_DRM_MAX 0x64ff
+
static linux_ioctl_function_t DRM( linux_ioctl);
static struct linux_ioctl_handler DRM( handler) = {DRM( linux_ioctl), LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX};
SYSINIT (DRM( register), SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_register_handler, &DRM( handler));
SYSUNINIT(DRM( unregister), SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_unregister_handler, &DRM( handler));
+#define LINUX_IOC_VOID IOC_VOID
+#define LINUX_IOC_IN IOC_OUT /* Linux has the values the other way around */
+#define LINUX_IOC_OUT IOC_IN
+
/*
* Linux emulation IOCTL
*/
static int
DRM(linux_ioctl)(DRM_STRUCTPROC *p, struct linux_ioctl_args* args)
{
+ u_long cmd = args->cmd;
+#define STK_PARAMS 128
+ union {
+ char stkbuf[STK_PARAMS];
+ long align;
+ } ubuf;
+ caddr_t data=NULL, memp=NULL;
+ u_int size = IOCPARM_LEN(cmd);
+ int error;
#if (__FreeBSD_version >= 500000)
- struct file *fp = p->td_proc->p_fd->fd_ofiles[args->fd];
+ struct file *fp;
#else
- struct file *fp = p->p_fd->fd_ofiles[args->fd];
-#endif
- u_long cmd = args->cmd;
- caddr_t data = (caddr_t) args->arg;
- /*
- * Pass the ioctl off to our standard handler.
- */
- return(fo_ioctl(fp, cmd, data, p));
+ struct file *fp = p->p_fd->fd_ofiles[args->fd];
+#endif
+ if ( size > STK_PARAMS ) {
+ if ( size > IOCPARM_MAX )
+ return EINVAL;
+ memp = malloc( (u_long)size, DRM(M_DRM), M_WAITOK );
+ data = memp;
+ } else {
+ data = ubuf.stkbuf;
+ }
+
+ if ( cmd & LINUX_IOC_IN ) {
+ if ( size ) {
+ error = copyin( (caddr_t)args->arg, data, (u_int)size );
+ if (error) {
+ if ( memp )
+ free( data, DRM(M_DRM) );
+ return error;
+ }
+ } else {
+ data = (caddr_t)args->arg;
+ }
+ } else if ( (cmd & LINUX_IOC_OUT) && size ) {
+ /*
+ * Zero the buffer so the user always
+ * gets back something deterministic.
+ */
+ bzero( data, size );
+ } else if ( cmd & LINUX_IOC_VOID ) {
+ *(caddr_t *)data = (caddr_t)args->arg;
+ }
+
+#if (__FreeBSD_version >= 500000)
+ if ( (error = fget( p, args->fd, &fp )) != 0 ) {
+ if ( memp )
+ free( memp, DRM(M_DRM) );
+ return (error);
+ }
+ error = fo_ioctl( fp, cmd, data, p->td_ucred, p );
+ fdrop( fp, p );
+#else
+ error = fo_ioctl( fp, cmd, data, p );
+#endif
+ if ( error == 0 && (cmd & LINUX_IOC_OUT) && size )
+ error = copyout( data, (caddr_t)args->arg, (u_int)size );
+ if ( memp )
+ free( memp, DRM(M_DRM) );
+ return error;
}
#endif /* DRM_LINUX */
diff --git a/bsd/drm_os_freebsd.h b/bsd/drm_os_freebsd.h
index 23838139..6f878d4f 100644
--- a/bsd/drm_os_freebsd.h
+++ b/bsd/drm_os_freebsd.h
@@ -65,7 +65,6 @@
#include <sys/proc.h>
#include <machine/../linux/linux.h>
#include <machine/../linux/linux_proto.h>
-#include "drm_linux.h"
#endif
#define DRM_TIME_SLICE (hz/20) /* Time slice for GLXContexts */
@@ -140,14 +139,18 @@ do { \
} \
} while (0)
-#define DRM_COPY_TO_USER_IOCTL(arg1, arg2, arg3) \
- *arg1 = arg2
-#define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \
- arg1 = *arg2
-#define DRM_COPY_TO_USER(arg1, arg2, arg3) \
- copyout(arg2, arg1, arg3)
-#define DRM_COPY_FROM_USER(arg1, arg2, arg3) \
- copyin(arg2, arg1, arg3)
+#define DRM_COPY_TO_USER_IOCTL(user, kern, size) \
+ if ( IOCPARM_LEN(cmd) != size) \
+ return EINVAL; \
+ *user = kern;
+#define DRM_COPY_FROM_USER_IOCTL(kern, user, size) \
+ if ( IOCPARM_LEN(cmd) != size) \
+ return EINVAL; \
+ kern = *user;
+#define DRM_COPY_TO_USER(user, kern, size) \
+ copyout(kern, user, size)
+#define DRM_COPY_FROM_USER(kern, user, size) \
+ copyin(user, kern, size)
/* Macros for userspace access with checking readability once */
/* FIXME: can't find equivalent functionality for nocheck yet.
* It's be slower than linux, but should be correct.
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index c00efb4c..f31c5c3d 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -165,7 +165,7 @@
#define pte_unmap(pte)
#endif
-#if LINUX_VERSION_CODE < 0x020500
+#if LINUX_VERSION_CODE < 0x020413 /* KERNEL_VERSION(2,4,19) */
static inline struct page * vmalloc_to_page(void * vmalloc_addr)
{
unsigned long addr = (unsigned long) vmalloc_addr;
diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c
index fc0b29aa..cd46110c 100644
--- a/linux-core/drm_agpsupport.c
+++ b/linux-core/drm_agpsupport.c
@@ -268,11 +268,11 @@ drm_agp_head_t *DRM(agp_init)(void)
case INTEL_I810: head->chipset = "Intel i810"; break;
case INTEL_I815: head->chipset = "Intel i815"; break;
-#if LINUX_VERSION_CODE >= 0x020415
+#if LINUX_VERSION_CODE >= 0x02040f /* KERNEL_VERSION(2,4,15) */
case INTEL_I820: head->chipset = "Intel i820"; break;
#endif
case INTEL_I840: head->chipset = "Intel i840"; break;
-#if LINUX_VERSION_CODE >= 0x020415
+#if LINUX_VERSION_CODE >= 0x02040f /* KERNEL_VERSION(2,4,15) */
case INTEL_I845: head->chipset = "Intel i845"; break;
#endif
case INTEL_I850: head->chipset = "Intel i850"; break;
diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c
index af6858d7..81bd7894 100644
--- a/linux-core/drm_drv.c
+++ b/linux-core/drm_drv.c
@@ -115,15 +115,15 @@
#ifndef DRIVER_FOPS
#define DRIVER_FOPS \
static struct file_operations DRM(fops) = { \
- owner: THIS_MODULE, \
- open: DRM(open), \
- flush: DRM(flush), \
- release: DRM(release), \
- ioctl: DRM(ioctl), \
- mmap: DRM(mmap), \
- read: DRM(read), \
- fasync: DRM(fasync), \
- poll: DRM(poll), \
+ .owner = THIS_MODULE, \
+ .open = DRM(open), \
+ .flush = DRM(flush), \
+ .release = DRM(release), \
+ .ioctl = DRM(ioctl), \
+ .mmap = DRM(mmap), \
+ .read = DRM(read), \
+ .fasync = DRM(fasync), \
+ .poll = DRM(poll), \
}
#endif
diff --git a/linux-core/drm_stub.c b/linux-core/drm_stub.c
index b1e78923..3c9c69eb 100644
--- a/linux-core/drm_stub.c
+++ b/linux-core/drm_stub.c
@@ -66,8 +66,8 @@ static int DRM(stub_open)(struct inode *inode, struct file *filp)
}
static struct file_operations DRM(stub_fops) = {
- owner: THIS_MODULE,
- open: DRM(stub_open)
+ .owner = THIS_MODULE,
+ .open = DRM(stub_open)
};
static int DRM(stub_getminor)(const char *name, struct file_operations *fops,
diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c
index c07c9aff..52dfd594 100644
--- a/linux-core/drm_vm.c
+++ b/linux-core/drm_vm.c
@@ -33,27 +33,27 @@
#include "drmP.h"
struct vm_operations_struct DRM(vm_ops) = {
- nopage: DRM(vm_nopage),
- open: DRM(vm_open),
- close: DRM(vm_close),
+ .nopage = DRM(vm_nopage),
+ .open = DRM(vm_open),
+ .close = DRM(vm_close),
};
struct vm_operations_struct DRM(vm_shm_ops) = {
- nopage: DRM(vm_shm_nopage),
- open: DRM(vm_open),
- close: DRM(vm_shm_close),
+ .nopage = DRM(vm_shm_nopage),
+ .open = DRM(vm_open),
+ .close = DRM(vm_shm_close),
};
struct vm_operations_struct DRM(vm_dma_ops) = {
- nopage: DRM(vm_dma_nopage),
- open: DRM(vm_open),
- close: DRM(vm_close),
+ .nopage = DRM(vm_dma_nopage),
+ .open = DRM(vm_open),
+ .close = DRM(vm_close),
};
struct vm_operations_struct DRM(vm_sg_ops) = {
- nopage: DRM(vm_sg_nopage),
- open: DRM(vm_open),
- close: DRM(vm_close),
+ .nopage = DRM(vm_sg_nopage),
+ .open = DRM(vm_open),
+ .close = DRM(vm_close),
};
struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
@@ -343,7 +343,7 @@ int DRM(mmap_dma)(struct file *filp, struct vm_area_struct *vma)
vma->vm_ops = &DRM(vm_dma_ops);
-#if LINUX_VERSION_CODE <= 0x020414
+#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
#else
vma->vm_flags |= VM_RESERVED; /* Don't swap */
@@ -473,7 +473,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
vma->vm_private_data = (void *)map;
/* Don't let this area swap. Change when
DRM_KERNEL advisory is supported. */
-#if LINUX_VERSION_CODE <= 0x020414
+#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
vma->vm_flags |= VM_LOCKED;
#else
vma->vm_flags |= VM_RESERVED;
@@ -482,7 +482,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
case _DRM_SCATTER_GATHER:
vma->vm_ops = &DRM(vm_sg_ops);
vma->vm_private_data = (void *)map;
-#if LINUX_VERSION_CODE <= 0x020414
+#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
vma->vm_flags |= VM_LOCKED;
#else
vma->vm_flags |= VM_RESERVED;
@@ -491,7 +491,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
default:
return -EINVAL; /* This should never happen. */
}
-#if LINUX_VERSION_CODE <= 0x020414
+#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
#else
vma->vm_flags |= VM_RESERVED; /* Don't swap */
diff --git a/linux-core/i810_dma.c b/linux-core/i810_dma.c
index a2899b5f..f4eef3a3 100644
--- a/linux-core/i810_dma.c
+++ b/linux-core/i810_dma.c
@@ -37,6 +37,7 @@
#include "i810_drm.h"
#include "i810_drv.h"
#include <linux/interrupt.h> /* For task queue support */
+#include <linux/delay.h>
#define I810_BUF_FREE 2
#define I810_BUF_CLIENT 1
@@ -129,14 +130,14 @@ static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
}
static struct file_operations i810_buffer_fops = {
- open: DRM(open),
- flush: DRM(flush),
- release: DRM(release),
- ioctl: DRM(ioctl),
- mmap: i810_mmap_buffers,
- read: DRM(read),
- fasync: DRM(fasync),
- poll: DRM(poll),
+ .open = DRM(open),
+ .flush = DRM(flush),
+ .release = DRM(release),
+ .ioctl = DRM(ioctl),
+ .mmap = i810_mmap_buffers,
+ .read = DRM(read),
+ .fasync = DRM(fasync),
+ .poll = DRM(poll),
};
int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
@@ -270,20 +271,24 @@ static unsigned long i810_alloc_page(drm_device_t *dev)
if(address == 0UL)
return 0;
-#if LINUX_VERSION_CODE < 0x020500
+#if LINUX_VERSION_CODE < 0x020409
atomic_inc(&virt_to_page(address)->count);
set_bit(PG_locked, &virt_to_page(address)->flags);
#else
get_page(virt_to_page(address));
+#if LINUX_VERSION_CODE < 0x020500
+ LockPage(virt_to_page(address));
+#else
SetPageLocked(virt_to_page(address));
#endif
+#endif
return address;
}
static void i810_free_page(drm_device_t *dev, unsigned long page)
{
if (page) {
-#if LINUX_VERSION_CODE < 0x020500
+#if LINUX_VERSION_CODE < 0x020409
atomic_dec(&virt_to_page(page)->count);
clear_bit(PG_locked, &virt_to_page(page)->flags);
wake_up(&virt_to_page(page)->wait);
@@ -337,8 +342,6 @@ static int i810_wait_ring(drm_device_t *dev, int n)
end = jiffies + (HZ*3);
while (ring->space < n) {
- int i;
-
ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
ring->space = ring->head - (ring->tail+8);
if (ring->space < 0) ring->space += ring->Size;
diff --git a/linux-core/i830_dma.c b/linux-core/i830_dma.c
index b9c89aab..643259fc 100644
--- a/linux-core/i830_dma.c
+++ b/linux-core/i830_dma.c
@@ -153,14 +153,14 @@ static int i830_freelist_put(drm_device_t *dev, drm_buf_t *buf)
}
static struct file_operations i830_buffer_fops = {
- open: DRM(open),
- flush: DRM(flush),
- release: DRM(release),
- ioctl: DRM(ioctl),
- mmap: i830_mmap_buffers,
- read: DRM(read),
- fasync: DRM(fasync),
- poll: DRM(poll),
+ .open = DRM(open),
+ .flush = DRM(flush),
+ .release = DRM(release),
+ .ioctl = DRM(ioctl),
+ .mmap = i830_mmap_buffers,
+ .read = DRM(read),
+ .fasync = DRM(fasync),
+ .poll = DRM(poll),
};
int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
@@ -303,20 +303,24 @@ static unsigned long i830_alloc_page(drm_device_t *dev)
if(address == 0UL)
return 0;
-#if LINUX_VERSION_CODE < 0x020500
+#if LINUX_VERSION_CODE < 0x020409
atomic_inc(&virt_to_page(address)->count);
set_bit(PG_locked, &virt_to_page(address)->flags);
#else
get_page(virt_to_page(address));
+#if LINUX_VERSION_CODE < 0x020500
+ LockPage(virt_to_page(address));
+#else
SetPageLocked(virt_to_page(address));
#endif
+#endif
return address;
}
static void i830_free_page(drm_device_t *dev, unsigned long page)
{
if (page) {
-#if LINUX_VERSION_CODE < 0x020500
+#if LINUX_VERSION_CODE < 0x020409
atomic_dec(&virt_to_page(page)->count);
clear_bit(PG_locked, &virt_to_page(page)->flags);
wake_up(&virt_to_page(page)->wait);
diff --git a/linux/Makefile.linux b/linux/Makefile.linux
index 893d4985..a8cd62a7 100644
--- a/linux/Makefile.linux
+++ b/linux/Makefile.linux
@@ -254,12 +254,12 @@ ChangeLog:
$(GAMMAOBJS): $(GAMMAHEADERS)
$(TDFXOBJS): $(TDFXHEADERS)
+$(R128OBJS): $(R128HEADERS)
+$(RADEONOBJS): $(RADEONHEADERS)
ifeq ($(AGP),1)
$(MGAOBJS): $(MGAHEADERS)
$(I810OBJS): $(I810HEADERS)
$(I830OBJS): $(I830HEADERS)
-$(R128OBJS): $(R128HEADERS)
-$(RADEONOBJS): $(RADEONHEADERS)
endif
clean cleandir::
diff --git a/linux/drmP.h b/linux/drmP.h
index c00efb4c..f31c5c3d 100644
--- a/linux/drmP.h
+++ b/linux/drmP.h
@@ -165,7 +165,7 @@
#define pte_unmap(pte)
#endif
-#if LINUX_VERSION_CODE < 0x020500
+#if LINUX_VERSION_CODE < 0x020413 /* KERNEL_VERSION(2,4,19) */
static inline struct page * vmalloc_to_page(void * vmalloc_addr)
{
unsigned long addr = (unsigned long) vmalloc_addr;
diff --git a/linux/drm_agpsupport.h b/linux/drm_agpsupport.h
index fc0b29aa..cd46110c 100644
--- a/linux/drm_agpsupport.h
+++ b/linux/drm_agpsupport.h
@@ -268,11 +268,11 @@ drm_agp_head_t *DRM(agp_init)(void)
case INTEL_I810: head->chipset = "Intel i810"; break;
case INTEL_I815: head->chipset = "Intel i815"; break;
-#if LINUX_VERSION_CODE >= 0x020415
+#if LINUX_VERSION_CODE >= 0x02040f /* KERNEL_VERSION(2,4,15) */
case INTEL_I820: head->chipset = "Intel i820"; break;
#endif
case INTEL_I840: head->chipset = "Intel i840"; break;
-#if LINUX_VERSION_CODE >= 0x020415
+#if LINUX_VERSION_CODE >= 0x02040f /* KERNEL_VERSION(2,4,15) */
case INTEL_I845: head->chipset = "Intel i845"; break;
#endif
case INTEL_I850: head->chipset = "Intel i850"; break;
diff --git a/linux/drm_drv.h b/linux/drm_drv.h
index af6858d7..81bd7894 100644
--- a/linux/drm_drv.h
+++ b/linux/drm_drv.h
@@ -115,15 +115,15 @@
#ifndef DRIVER_FOPS
#define DRIVER_FOPS \
static struct file_operations DRM(fops) = { \
- owner: THIS_MODULE, \
- open: DRM(open), \
- flush: DRM(flush), \
- release: DRM(release), \
- ioctl: DRM(ioctl), \
- mmap: DRM(mmap), \
- read: DRM(read), \
- fasync: DRM(fasync), \
- poll: DRM(poll), \
+ .owner = THIS_MODULE, \
+ .open = DRM(open), \
+ .flush = DRM(flush), \
+ .release = DRM(release), \
+ .ioctl = DRM(ioctl), \
+ .mmap = DRM(mmap), \
+ .read = DRM(read), \
+ .fasync = DRM(fasync), \
+ .poll = DRM(poll), \
}
#endif
diff --git a/linux/drm_stub.h b/linux/drm_stub.h
index b1e78923..3c9c69eb 100644
--- a/linux/drm_stub.h
+++ b/linux/drm_stub.h
@@ -66,8 +66,8 @@ static int DRM(stub_open)(struct inode *inode, struct file *filp)
}
static struct file_operations DRM(stub_fops) = {
- owner: THIS_MODULE,
- open: DRM(stub_open)
+ .owner = THIS_MODULE,
+ .open = DRM(stub_open)
};
static int DRM(stub_getminor)(const char *name, struct file_operations *fops,
diff --git a/linux/drm_vm.h b/linux/drm_vm.h
index c07c9aff..52dfd594 100644
--- a/linux/drm_vm.h
+++ b/linux/drm_vm.h
@@ -33,27 +33,27 @@
#include "drmP.h"
struct vm_operations_struct DRM(vm_ops) = {
- nopage: DRM(vm_nopage),
- open: DRM(vm_open),
- close: DRM(vm_close),
+ .nopage = DRM(vm_nopage),
+ .open = DRM(vm_open),
+ .close = DRM(vm_close),
};
struct vm_operations_struct DRM(vm_shm_ops) = {
- nopage: DRM(vm_shm_nopage),
- open: DRM(vm_open),
- close: DRM(vm_shm_close),
+ .nopage = DRM(vm_shm_nopage),
+ .open = DRM(vm_open),
+ .close = DRM(vm_shm_close),
};
struct vm_operations_struct DRM(vm_dma_ops) = {
- nopage: DRM(vm_dma_nopage),
- open: DRM(vm_open),
- close: DRM(vm_close),
+ .nopage = DRM(vm_dma_nopage),
+ .open = DRM(vm_open),
+ .close = DRM(vm_close),
};
struct vm_operations_struct DRM(vm_sg_ops) = {
- nopage: DRM(vm_sg_nopage),
- open: DRM(vm_open),
- close: DRM(vm_close),
+ .nopage = DRM(vm_sg_nopage),
+ .open = DRM(vm_open),
+ .close = DRM(vm_close),
};
struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
@@ -343,7 +343,7 @@ int DRM(mmap_dma)(struct file *filp, struct vm_area_struct *vma)
vma->vm_ops = &DRM(vm_dma_ops);
-#if LINUX_VERSION_CODE <= 0x020414
+#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
#else
vma->vm_flags |= VM_RESERVED; /* Don't swap */
@@ -473,7 +473,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
vma->vm_private_data = (void *)map;
/* Don't let this area swap. Change when
DRM_KERNEL advisory is supported. */
-#if LINUX_VERSION_CODE <= 0x020414
+#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
vma->vm_flags |= VM_LOCKED;
#else
vma->vm_flags |= VM_RESERVED;
@@ -482,7 +482,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
case _DRM_SCATTER_GATHER:
vma->vm_ops = &DRM(vm_sg_ops);
vma->vm_private_data = (void *)map;
-#if LINUX_VERSION_CODE <= 0x020414
+#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
vma->vm_flags |= VM_LOCKED;
#else
vma->vm_flags |= VM_RESERVED;
@@ -491,7 +491,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
default:
return -EINVAL; /* This should never happen. */
}
-#if LINUX_VERSION_CODE <= 0x020414
+#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
#else
vma->vm_flags |= VM_RESERVED; /* Don't swap */
diff --git a/linux/i810_dma.c b/linux/i810_dma.c
index a2899b5f..f4eef3a3 100644
--- a/linux/i810_dma.c
+++ b/linux/i810_dma.c
@@ -37,6 +37,7 @@
#include "i810_drm.h"
#include "i810_drv.h"
#include <linux/interrupt.h> /* For task queue support */
+#include <linux/delay.h>
#define I810_BUF_FREE 2
#define I810_BUF_CLIENT 1
@@ -129,14 +130,14 @@ static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
}
static struct file_operations i810_buffer_fops = {
- open: DRM(open),
- flush: DRM(flush),
- release: DRM(release),
- ioctl: DRM(ioctl),
- mmap: i810_mmap_buffers,
- read: DRM(read),
- fasync: DRM(fasync),
- poll: DRM(poll),
+ .open = DRM(open),
+ .flush = DRM(flush),
+ .release = DRM(release),
+ .ioctl = DRM(ioctl),
+ .mmap = i810_mmap_buffers,
+ .read = DRM(read),
+ .fasync = DRM(fasync),
+ .poll = DRM(poll),
};
int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
@@ -270,20 +271,24 @@ static unsigned long i810_alloc_page(drm_device_t *dev)
if(address == 0UL)
return 0;
-#if LINUX_VERSION_CODE < 0x020500
+#if LINUX_VERSION_CODE < 0x020409
atomic_inc(&virt_to_page(address)->count);
set_bit(PG_locked, &virt_to_page(address)->flags);
#else
get_page(virt_to_page(address));
+#if LINUX_VERSION_CODE < 0x020500
+ LockPage(virt_to_page(address));
+#else
SetPageLocked(virt_to_page(address));
#endif
+#endif
return address;
}
static void i810_free_page(drm_device_t *dev, unsigned long page)
{
if (page) {
-#if LINUX_VERSION_CODE < 0x020500
+#if LINUX_VERSION_CODE < 0x020409
atomic_dec(&virt_to_page(page)->count);
clear_bit(PG_locked, &virt_to_page(page)->flags);
wake_up(&virt_to_page(page)->wait);
@@ -337,8 +342,6 @@ static int i810_wait_ring(drm_device_t *dev, int n)
end = jiffies + (HZ*3);
while (ring->space < n) {
- int i;
-
ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
ring->space = ring->head - (ring->tail+8);
if (ring->space < 0) ring->space += ring->Size;
diff --git a/linux/i830_dma.c b/linux/i830_dma.c
index b9c89aab..643259fc 100644
--- a/linux/i830_dma.c
+++ b/linux/i830_dma.c
@@ -153,14 +153,14 @@ static int i830_freelist_put(drm_device_t *dev, drm_buf_t *buf)
}
static struct file_operations i830_buffer_fops = {
- open: DRM(open),
- flush: DRM(flush),
- release: DRM(release),
- ioctl: DRM(ioctl),
- mmap: i830_mmap_buffers,
- read: DRM(read),
- fasync: DRM(fasync),
- poll: DRM(poll),
+ .open = DRM(open),
+ .flush = DRM(flush),
+ .release = DRM(release),
+ .ioctl = DRM(ioctl),
+ .mmap = i830_mmap_buffers,
+ .read = DRM(read),
+ .fasync = DRM(fasync),
+ .poll = DRM(poll),
};
int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
@@ -303,20 +303,24 @@ static unsigned long i830_alloc_page(drm_device_t *dev)
if(address == 0UL)
return 0;
-#if LINUX_VERSION_CODE < 0x020500
+#if LINUX_VERSION_CODE < 0x020409
atomic_inc(&virt_to_page(address)->count);
set_bit(PG_locked, &virt_to_page(address)->flags);
#else
get_page(virt_to_page(address));
+#if LINUX_VERSION_CODE < 0x020500
+ LockPage(virt_to_page(address));
+#else
SetPageLocked(virt_to_page(address));
#endif
+#endif
return address;
}
static void i830_free_page(drm_device_t *dev, unsigned long page)
{
if (page) {
-#if LINUX_VERSION_CODE < 0x020500
+#if LINUX_VERSION_CODE < 0x020409
atomic_dec(&virt_to_page(page)->count);
clear_bit(PG_locked, &virt_to_page(page)->flags);
wake_up(&virt_to_page(page)->wait);
diff --git a/shared-core/mga_drv.h b/shared-core/mga_drv.h
index 51bc706e..0845009b 100644
--- a/shared-core/mga_drv.h
+++ b/shared-core/mga_drv.h
@@ -38,7 +38,7 @@ typedef struct drm_mga_primary_buffer {
u32 tail;
int space;
- int wrapped;
+ volatile long wrapped;
volatile u32 *status;
diff --git a/shared-core/mga_state.c b/shared-core/mga_state.c
index adf67de3..734432d5 100644
--- a/shared-core/mga_state.c
+++ b/shared-core/mga_state.c
@@ -37,7 +37,6 @@
#include "drm.h"
#include "mga_drm.h"
#include "mga_drv.h"
-#include "drm.h"
/* ================================================================
diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c
index d56a9002..01069e49 100644
--- a/shared-core/radeon_cp.c
+++ b/shared-core/radeon_cp.c
@@ -925,6 +925,24 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev,
RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 );
+ /* Writeback doesn't seem to work everywhere, test it first */
+ DRM_WRITE32( &dev_priv->scratch[1], 0 );
+ RADEON_WRITE( RADEON_SCRATCH_REG1, 0xdeadbeef );
+
+ for ( tmp = 0 ; tmp < dev_priv->usec_timeout ; tmp++ ) {
+ if ( DRM_READ32( &dev_priv->scratch[1] ) == 0xdeadbeef )
+ break;
+ DRM_UDELAY( 1 );
+ }
+
+ if ( tmp < dev_priv->usec_timeout ) {
+ dev_priv->writeback_works = 1;
+ DRM_DEBUG( "writeback test succeeded, tmp=%d\n", tmp );
+ } else {
+ dev_priv->writeback_works = 0;
+ DRM_DEBUG( "writeback test failed\n" );
+ }
+
dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
RADEON_WRITE( RADEON_LAST_FRAME_REG,
dev_priv->sarea_priv->last_frame );
@@ -1456,8 +1474,8 @@ drm_buf_t *radeon_freelist_get( drm_device_t *dev )
start = dev_priv->last_buf;
for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
- u32 done_age = DRM_READ32(&dev_priv->scratch[1]);
-
+ u32 done_age = GET_SCRATCH( 1 );
+ DRM_DEBUG("done_age = %d\n",done_age);
for ( i = start ; i < dma->buf_count ; i++ ) {
buf = dma->buflist[i];
buf_priv = buf->dev_private;
diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h
index 57cd5f4f..7c341b39 100644
--- a/shared-core/radeon_drv.h
+++ b/shared-core/radeon_drv.h
@@ -76,6 +76,7 @@ typedef struct drm_radeon_private {
drm_radeon_freelist_t *tail;
int last_buf;
volatile u32 *scratch;
+ int writeback_works;
int usec_timeout;
@@ -233,6 +234,10 @@ extern int radeon_cp_flip( DRM_IOCTL_ARGS );
#define RADEON_SCRATCH_UMSK 0x0770
#define RADEON_SCRATCH_ADDR 0x0774
+#define GET_SCRATCH( x ) (dev_priv->writeback_works \
+ ? DRM_READ32( &dev_priv->scratch[(x)] ) \
+ : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
+
#define RADEON_HOST_PATH_CNTL 0x0130
# define RADEON_HDP_SOFT_RESET (1 << 26)
# define RADEON_HDP_WC_TIMEOUT_MASK (7 << 28)
diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c
index 7b2dbdfb..7f84e739 100644
--- a/shared-core/radeon_state.c
+++ b/shared-core/radeon_state.c
@@ -1936,6 +1936,19 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
if ( i < cmdbuf->nbox ) {
if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) ))
return DRM_ERR(EFAULT);
+ /* FIXME The second and subsequent times round this loop, send a
+ * WAIT_UNTIL_3D_IDLE before calling emit_clip_rect(). This
+ * fixes a lockup on fast machines when sending several
+ * cliprects with a cmdbuf, as when waving a 2D window over
+ * a 3D window. Something in the commands from user space
+ * seems to hang the card when they're sent several times
+ * in a row. That would be the correct place to fix it but
+ * this works around it until I can figure that out - Tim Smith */
+ if ( i ) {
+ BEGIN_RING( 2 );
+ RADEON_WAIT_UNTIL_3D_IDLE();
+ ADVANCE_RING();
+ }
radeon_emit_clip_rect( dev_priv, &box );
}
@@ -1944,7 +1957,6 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
ADVANCE_RING();
} while ( ++i < cmdbuf->nbox );
-
if (cmdbuf->nbox == 1)
cmdbuf->nbox = 0;
@@ -2107,14 +2119,14 @@ int radeon_cp_getparam( DRM_IOCTL_ARGS )
break;
case RADEON_PARAM_LAST_FRAME:
dev_priv->stats.last_frame_reads++;
- value = DRM_READ32(&dev_priv->scratch[0]);
+ value = GET_SCRATCH( 0 );
break;
case RADEON_PARAM_LAST_DISPATCH:
- value = DRM_READ32(&dev_priv->scratch[1]);
+ value = GET_SCRATCH( 1 );
break;
case RADEON_PARAM_LAST_CLEAR:
dev_priv->stats.last_clear_reads++;
- value = DRM_READ32(&dev_priv->scratch[2]);
+ value = GET_SCRATCH( 2 );
break;
default:
return DRM_ERR(EINVAL);
diff --git a/shared/mga_drv.h b/shared/mga_drv.h
index 51bc706e..0845009b 100644
--- a/shared/mga_drv.h
+++ b/shared/mga_drv.h
@@ -38,7 +38,7 @@ typedef struct drm_mga_primary_buffer {
u32 tail;
int space;
- int wrapped;
+ volatile long wrapped;
volatile u32 *status;
diff --git a/shared/mga_state.c b/shared/mga_state.c
index adf67de3..734432d5 100644
--- a/shared/mga_state.c
+++ b/shared/mga_state.c
@@ -37,7 +37,6 @@
#include "drm.h"
#include "mga_drm.h"
#include "mga_drv.h"
-#include "drm.h"
/* ================================================================
diff --git a/shared/radeon_cp.c b/shared/radeon_cp.c
index d56a9002..01069e49 100644
--- a/shared/radeon_cp.c
+++ b/shared/radeon_cp.c
@@ -925,6 +925,24 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev,
RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 );
+ /* Writeback doesn't seem to work everywhere, test it first */
+ DRM_WRITE32( &dev_priv->scratch[1], 0 );
+ RADEON_WRITE( RADEON_SCRATCH_REG1, 0xdeadbeef );
+
+ for ( tmp = 0 ; tmp < dev_priv->usec_timeout ; tmp++ ) {
+ if ( DRM_READ32( &dev_priv->scratch[1] ) == 0xdeadbeef )
+ break;
+ DRM_UDELAY( 1 );
+ }
+
+ if ( tmp < dev_priv->usec_timeout ) {
+ dev_priv->writeback_works = 1;
+ DRM_DEBUG( "writeback test succeeded, tmp=%d\n", tmp );
+ } else {
+ dev_priv->writeback_works = 0;
+ DRM_DEBUG( "writeback test failed\n" );
+ }
+
dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
RADEON_WRITE( RADEON_LAST_FRAME_REG,
dev_priv->sarea_priv->last_frame );
@@ -1456,8 +1474,8 @@ drm_buf_t *radeon_freelist_get( drm_device_t *dev )
start = dev_priv->last_buf;
for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
- u32 done_age = DRM_READ32(&dev_priv->scratch[1]);
-
+ u32 done_age = GET_SCRATCH( 1 );
+ DRM_DEBUG("done_age = %d\n",done_age);
for ( i = start ; i < dma->buf_count ; i++ ) {
buf = dma->buflist[i];
buf_priv = buf->dev_private;
diff --git a/shared/radeon_drv.h b/shared/radeon_drv.h
index 57cd5f4f..7c341b39 100644
--- a/shared/radeon_drv.h
+++ b/shared/radeon_drv.h
@@ -76,6 +76,7 @@ typedef struct drm_radeon_private {
drm_radeon_freelist_t *tail;
int last_buf;
volatile u32 *scratch;
+ int writeback_works;
int usec_timeout;
@@ -233,6 +234,10 @@ extern int radeon_cp_flip( DRM_IOCTL_ARGS );
#define RADEON_SCRATCH_UMSK 0x0770
#define RADEON_SCRATCH_ADDR 0x0774
+#define GET_SCRATCH( x ) (dev_priv->writeback_works \
+ ? DRM_READ32( &dev_priv->scratch[(x)] ) \
+ : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
+
#define RADEON_HOST_PATH_CNTL 0x0130
# define RADEON_HDP_SOFT_RESET (1 << 26)
# define RADEON_HDP_WC_TIMEOUT_MASK (7 << 28)
diff --git a/shared/radeon_state.c b/shared/radeon_state.c
index 7b2dbdfb..7f84e739 100644
--- a/shared/radeon_state.c
+++ b/shared/radeon_state.c
@@ -1936,6 +1936,19 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
if ( i < cmdbuf->nbox ) {
if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) ))
return DRM_ERR(EFAULT);
+ /* FIXME The second and subsequent times round this loop, send a
+ * WAIT_UNTIL_3D_IDLE before calling emit_clip_rect(). This
+ * fixes a lockup on fast machines when sending several
+ * cliprects with a cmdbuf, as when waving a 2D window over
+ * a 3D window. Something in the commands from user space
+ * seems to hang the card when they're sent several times
+ * in a row. That would be the correct place to fix it but
+ * this works around it until I can figure that out - Tim Smith */
+ if ( i ) {
+ BEGIN_RING( 2 );
+ RADEON_WAIT_UNTIL_3D_IDLE();
+ ADVANCE_RING();
+ }
radeon_emit_clip_rect( dev_priv, &box );
}
@@ -1944,7 +1957,6 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
ADVANCE_RING();
} while ( ++i < cmdbuf->nbox );
-
if (cmdbuf->nbox == 1)
cmdbuf->nbox = 0;
@@ -2107,14 +2119,14 @@ int radeon_cp_getparam( DRM_IOCTL_ARGS )
break;
case RADEON_PARAM_LAST_FRAME:
dev_priv->stats.last_frame_reads++;
- value = DRM_READ32(&dev_priv->scratch[0]);
+ value = GET_SCRATCH( 0 );
break;
case RADEON_PARAM_LAST_DISPATCH:
- value = DRM_READ32(&dev_priv->scratch[1]);
+ value = GET_SCRATCH( 1 );
break;
case RADEON_PARAM_LAST_CLEAR:
dev_priv->stats.last_clear_reads++;
- value = DRM_READ32(&dev_priv->scratch[2]);
+ value = GET_SCRATCH( 2 );
break;
default:
return DRM_ERR(EINVAL);