diff options
-rw-r--r-- | bsd-core/drm_drv.c | 74 | ||||
-rw-r--r-- | bsd-core/drm_os_freebsd.h | 21 | ||||
-rw-r--r-- | bsd/drm_drv.h | 74 | ||||
-rw-r--r-- | bsd/drm_os_freebsd.h | 21 | ||||
-rw-r--r-- | linux-core/drmP.h | 2 | ||||
-rw-r--r-- | linux-core/drm_agpsupport.c | 4 | ||||
-rw-r--r-- | linux-core/drm_drv.c | 18 | ||||
-rw-r--r-- | linux-core/drm_stub.c | 4 | ||||
-rw-r--r-- | linux-core/drm_vm.c | 32 | ||||
-rw-r--r-- | linux-core/i810_dma.c | 27 | ||||
-rw-r--r-- | linux-core/i830_dma.c | 24 | ||||
-rw-r--r-- | linux/Makefile.linux | 4 | ||||
-rw-r--r-- | linux/drmP.h | 2 | ||||
-rw-r--r-- | linux/drm_agpsupport.h | 4 | ||||
-rw-r--r-- | linux/drm_drv.h | 18 | ||||
-rw-r--r-- | linux/drm_stub.h | 4 | ||||
-rw-r--r-- | linux/drm_vm.h | 32 | ||||
-rw-r--r-- | linux/i810_dma.c | 27 | ||||
-rw-r--r-- | linux/i830_dma.c | 24 | ||||
-rw-r--r-- | shared-core/mga_drv.h | 2 | ||||
-rw-r--r-- | shared-core/mga_state.c | 1 | ||||
-rw-r--r-- | shared-core/radeon_cp.c | 22 | ||||
-rw-r--r-- | shared-core/radeon_drv.h | 5 | ||||
-rw-r--r-- | shared-core/radeon_state.c | 20 | ||||
-rw-r--r-- | shared/mga_drv.h | 2 | ||||
-rw-r--r-- | shared/mga_state.c | 1 | ||||
-rw-r--r-- | shared/radeon_cp.c | 22 | ||||
-rw-r--r-- | shared/radeon_drv.h | 5 | ||||
-rw-r--r-- | shared/radeon_state.c | 20 |
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); |