diff options
author | Brian Paul <brian.paul@tungstengraphics.com> | 2002-11-15 01:59:39 +0000 |
---|---|---|
committer | Brian Paul <brian.paul@tungstengraphics.com> | 2002-11-15 01:59:39 +0000 |
commit | 683fe4276a435f4381cac8fbb457cbbd25471ffd (patch) | |
tree | 63432d5b6f275348852ecef24faea26434846a29 | |
parent | 878c8869ab2897fc7cb1c5fd639b18a977620b97 (diff) |
merge from trunk
51 files changed, 906 insertions, 251 deletions
diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h index 1adaa0e5..b7b21da4 100644 --- a/bsd-core/drmP.h +++ b/bsd-core/drmP.h @@ -448,6 +448,7 @@ struct drm_device { /* Context support */ #ifdef __FreeBSD__ int irq; /* Interrupt used by board */ + int irqrid; /* Interrupt used by board */ struct resource *irqr; /* Resource for interrupt used by board */ #elif defined(__NetBSD__) struct pci_attach_args pa; diff --git a/bsd-core/drm_dma.c b/bsd-core/drm_dma.c index 4593a712..5632b5a2 100644 --- a/bsd-core/drm_dma.c +++ b/bsd-core/drm_dma.c @@ -41,12 +41,6 @@ #define __HAVE_SHARED_IRQ 0 #endif -#if __HAVE_SHARED_IRQ -#define DRM_IRQ_TYPE SA_SHIRQ -#else -#define DRM_IRQ_TYPE 0 -#endif - #if __HAVE_DMA int DRM(dma_setup)( drm_device_t *dev ) @@ -503,7 +497,6 @@ int DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma) int DRM(irq_install)( drm_device_t *dev, int irq ) { - int rid; int retcode; if ( !irq ) @@ -535,18 +528,24 @@ int DRM(irq_install)( drm_device_t *dev, int irq ) DRM(driver_irq_preinstall)( dev ); /* Install handler */ - rid = 0; - dev->irqr = bus_alloc_resource(dev->device, SYS_RES_IRQ, &rid, + dev->irqrid = 0; + dev->irqr = bus_alloc_resource(dev->device, SYS_RES_IRQ, &dev->irqrid, 0, ~0, 1, RF_SHAREABLE); - if (!dev->irqr) + if (!dev->irqr) { + DRM_LOCK; + dev->irq = 0; + dev->irqrid = 0; + DRM_UNLOCK; return ENOENT; + } retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY, DRM(dma_service), dev, &dev->irqh); if ( retcode ) { DRM_LOCK; - bus_release_resource(dev->device, SYS_RES_IRQ, 0, dev->irqr); + bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, dev->irqr); dev->irq = 0; + dev->irqrid = 0; DRM_UNLOCK; return retcode; } @@ -560,10 +559,13 @@ int DRM(irq_install)( drm_device_t *dev, int irq ) int DRM(irq_uninstall)( drm_device_t *dev ) { int irq; - + int irqrid; + DRM_LOCK; irq = dev->irq; + irqrid = dev->irqrid; dev->irq = 0; + dev->irqrid = 0; DRM_UNLOCK; if ( !irq ) @@ -574,7 +576,7 @@ int DRM(irq_uninstall)( drm_device_t *dev ) DRM(driver_irq_uninstall)( dev ); bus_teardown_intr(dev->device, dev->irqr, dev->irqh); - bus_release_resource(dev->device, SYS_RES_IRQ, 0, dev->irqr); + bus_release_resource(dev->device, SYS_RES_IRQ, irqrid, dev->irqr); return 0; } diff --git a/bsd-core/drm_drv.c b/bsd-core/drm_drv.c index 872f6bc6..4a6fc15f 100644 --- a/bsd-core/drm_drv.c +++ b/bsd-core/drm_drv.c @@ -1037,7 +1037,11 @@ int DRM(ioctl)( DRM_IOCTL_ARGS ) case FIOGETOWN: atomic_dec(&dev->ioctl_count); +#if (__FreeBSD_version >= 500000) + *(int *) data = fgetown(&dev->buf_sigio); +#else *(int *) data = fgetown(dev->buf_sigio); +#endif return 0; } #endif /* __FreeBSD__ */ diff --git a/bsd-core/mga/Makefile b/bsd-core/mga/Makefile index 13e43c46..a280e024 100644 --- a/bsd-core/mga/Makefile +++ b/bsd-core/mga/Makefile @@ -3,7 +3,7 @@ .PATH: ${.CURDIR}/.. KMOD= mga NOMAN= YES -SRCS= mga_drv.c mga_state.c mga_warp.c mga_dma.c +SRCS= mga_drv.c mga_state.c mga_warp.c mga_dma.c mga_irq.c SRCS+= device_if.h bus_if.h pci_if.h opt_drm.h CFLAGS+= ${DEBUG_FLAGS} -I. -I.. diff --git a/bsd-core/r128/Makefile b/bsd-core/r128/Makefile index 83f78482..2d2e7e4f 100644 --- a/bsd-core/r128/Makefile +++ b/bsd-core/r128/Makefile @@ -3,7 +3,7 @@ .PATH: ${.CURDIR}/.. KMOD = r128 NOMAN= YES -SRCS = r128_cce.c r128_drv.c r128_state.c +SRCS = r128_cce.c r128_drv.c r128_state.c r128_irq.c SRCS += device_if.h bus_if.h pci_if.h opt_drm.h CFLAGS += ${DEBUG_FLAGS} -I. -I.. diff --git a/bsd/Imakefile b/bsd/Imakefile index 575e72b4..fddf8f53 100644 --- a/bsd/Imakefile +++ b/bsd/Imakefile @@ -1,5 +1,4 @@ - -XCOMM $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/Imakefile,v 1.8 2001/12/13 00:24:45 alanh Exp $ +XCOMM $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/Imakefile,v 1.9 2002/02/27 22:18:10 tsi Exp $ XCOMM This is a kludge until we determine how best to build the XCOMM kernel-specific device driver. This allows us to continue @@ -20,10 +19,12 @@ all:: clean:: $(MAKE) -f Makefile.bsd clean +LinkSourceFile(drm_sarea.h,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(mga.h,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(mga_dma.c,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(mga_drm.h,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(mga_drv.h,$(XF86OSSRC)/shared/drm/kernel) +LinkSourceFile(mga_irq.c,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(mga_state.c,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(mga_ucode.h,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(mga_warp.c,$(XF86OSSRC)/shared/drm/kernel) @@ -31,6 +32,7 @@ LinkSourceFile(r128.h,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(r128_cce.c,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(r128_drm.h,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(r128_drv.h,$(XF86OSSRC)/shared/drm/kernel) +LinkSourceFile(r128_irq.c,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(r128_state.c,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(radeon.h,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(radeon_cp.c,$(XF86OSSRC)/shared/drm/kernel) @@ -448,6 +448,7 @@ struct drm_device { /* Context support */ #ifdef __FreeBSD__ int irq; /* Interrupt used by board */ + int irqrid; /* Interrupt used by board */ struct resource *irqr; /* Resource for interrupt used by board */ #elif defined(__NetBSD__) struct pci_attach_args pa; diff --git a/bsd/drm_dma.h b/bsd/drm_dma.h index 4593a712..5632b5a2 100644 --- a/bsd/drm_dma.h +++ b/bsd/drm_dma.h @@ -41,12 +41,6 @@ #define __HAVE_SHARED_IRQ 0 #endif -#if __HAVE_SHARED_IRQ -#define DRM_IRQ_TYPE SA_SHIRQ -#else -#define DRM_IRQ_TYPE 0 -#endif - #if __HAVE_DMA int DRM(dma_setup)( drm_device_t *dev ) @@ -503,7 +497,6 @@ int DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma) int DRM(irq_install)( drm_device_t *dev, int irq ) { - int rid; int retcode; if ( !irq ) @@ -535,18 +528,24 @@ int DRM(irq_install)( drm_device_t *dev, int irq ) DRM(driver_irq_preinstall)( dev ); /* Install handler */ - rid = 0; - dev->irqr = bus_alloc_resource(dev->device, SYS_RES_IRQ, &rid, + dev->irqrid = 0; + dev->irqr = bus_alloc_resource(dev->device, SYS_RES_IRQ, &dev->irqrid, 0, ~0, 1, RF_SHAREABLE); - if (!dev->irqr) + if (!dev->irqr) { + DRM_LOCK; + dev->irq = 0; + dev->irqrid = 0; + DRM_UNLOCK; return ENOENT; + } retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY, DRM(dma_service), dev, &dev->irqh); if ( retcode ) { DRM_LOCK; - bus_release_resource(dev->device, SYS_RES_IRQ, 0, dev->irqr); + bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, dev->irqr); dev->irq = 0; + dev->irqrid = 0; DRM_UNLOCK; return retcode; } @@ -560,10 +559,13 @@ int DRM(irq_install)( drm_device_t *dev, int irq ) int DRM(irq_uninstall)( drm_device_t *dev ) { int irq; - + int irqrid; + DRM_LOCK; irq = dev->irq; + irqrid = dev->irqrid; dev->irq = 0; + dev->irqrid = 0; DRM_UNLOCK; if ( !irq ) @@ -574,7 +576,7 @@ int DRM(irq_uninstall)( drm_device_t *dev ) DRM(driver_irq_uninstall)( dev ); bus_teardown_intr(dev->device, dev->irqr, dev->irqh); - bus_release_resource(dev->device, SYS_RES_IRQ, 0, dev->irqr); + bus_release_resource(dev->device, SYS_RES_IRQ, irqrid, dev->irqr); return 0; } diff --git a/bsd/drm_drv.h b/bsd/drm_drv.h index 872f6bc6..4a6fc15f 100644 --- a/bsd/drm_drv.h +++ b/bsd/drm_drv.h @@ -1037,7 +1037,11 @@ int DRM(ioctl)( DRM_IOCTL_ARGS ) case FIOGETOWN: atomic_dec(&dev->ioctl_count); +#if (__FreeBSD_version >= 500000) + *(int *) data = fgetown(&dev->buf_sigio); +#else *(int *) data = fgetown(dev->buf_sigio); +#endif return 0; } #endif /* __FreeBSD__ */ diff --git a/bsd/mga/Makefile b/bsd/mga/Makefile index 13e43c46..a280e024 100644 --- a/bsd/mga/Makefile +++ b/bsd/mga/Makefile @@ -3,7 +3,7 @@ .PATH: ${.CURDIR}/.. KMOD= mga NOMAN= YES -SRCS= mga_drv.c mga_state.c mga_warp.c mga_dma.c +SRCS= mga_drv.c mga_state.c mga_warp.c mga_dma.c mga_irq.c SRCS+= device_if.h bus_if.h pci_if.h opt_drm.h CFLAGS+= ${DEBUG_FLAGS} -I. -I.. diff --git a/bsd/r128/Makefile b/bsd/r128/Makefile index 83f78482..2d2e7e4f 100644 --- a/bsd/r128/Makefile +++ b/bsd/r128/Makefile @@ -3,7 +3,7 @@ .PATH: ${.CURDIR}/.. KMOD = r128 NOMAN= YES -SRCS = r128_cce.c r128_drv.c r128_state.c +SRCS = r128_cce.c r128_drv.c r128_state.c r128_irq.c SRCS += device_if.h bus_if.h pci_if.h opt_drm.h CFLAGS += ${DEBUG_FLAGS} -I. -I.. diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c index 8d3a20d1..0532a1ec 100644 --- a/libdrm/xf86drm.c +++ b/libdrm/xf86drm.c @@ -27,13 +27,14 @@ * Authors: Rickard E. (Rik) Faith <faith@valinux.com> * Kevin E. Martin <martin@valinux.com> * - * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c,v 1.25 2001/08/27 17:40:59 dawes Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c,v 1.28 2002/10/16 01:26:49 dawes Exp $ * */ #ifdef XFree86Server # include "xf86.h" # include "xf86_OSproc.h" +# include "drm.h" # include "xf86_ansic.h" # define _DRM_MALLOC xalloc # define _DRM_FREE xfree @@ -66,6 +67,7 @@ extern int xf86RemoveSIGIOHandler(int fd); # define _DRM_MALLOC Xmalloc # define _DRM_FREE Xfree # endif +# include "drm.h" #endif /* No longer needed with CVS kernel modules on alpha @@ -81,7 +83,6 @@ extern unsigned long _bus_base(void); #endif #include "xf86drm.h" -#include "drm.h" #ifndef DRM_MAJOR #define DRM_MAJOR 226 /* Linux */ @@ -197,7 +198,6 @@ static int drmOpenDevice(long dev, int minor) stat_t st; char buf[64]; int fd; - mode_t dirmode = DRM_DEV_DIRMODE; mode_t devmode = DRM_DEV_MODE; int isroot = !geteuid(); #if defined(XFree86Server) @@ -209,23 +209,16 @@ static int drmOpenDevice(long dev, int minor) #if defined(XFree86Server) devmode = xf86ConfigDRI.mode ? xf86ConfigDRI.mode : DRM_DEV_MODE; - dirmode = (devmode & S_IRUSR) ? S_IXUSR : 0; - dirmode |= (devmode & S_IRGRP) ? S_IXGRP : 0; - dirmode |= (devmode & S_IROTH) ? S_IXOTH : 0; - dirmode |= devmode; devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH); group = (xf86ConfigDRI.group >= 0) ? xf86ConfigDRI.group : DRM_DEV_GID; #endif if (stat(DRM_DIR_NAME, &st)) { if (!isroot) return DRM_ERR_NOT_ROOT; - remove(DRM_DIR_NAME); - mkdir(DRM_DIR_NAME, dirmode); + mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE); + chown(DRM_DIR_NAME, 0, 0); /* root:root */ + chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE); } -#if defined(XFree86Server) - chown(DRM_DIR_NAME, user, group); - chmod(DRM_DIR_NAME, dirmode); -#endif sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor); drmMsg("drmOpenDevice: node name is %s\n", buf); diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 52dfd594..683c0857 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -71,7 +71,7 @@ struct page *DRM(vm_nopage)(struct vm_area_struct *vma, * Find the right map */ - if(!dev->agp->cant_use_aperture) goto vm_nopage_error; + if(!dev->agp || !dev->agp->cant_use_aperture) goto vm_nopage_error; list_for_each(list, &dev->maplist->head) { r_list = (drm_map_list_t *)list; @@ -408,7 +408,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma) if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) { vma->vm_flags &= VM_MAYWRITE; -#if defined(__i386__) +#if defined(__i386__) || defined(__x86_64__) pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW; #else /* Ye gads this is ugly. With more thought @@ -435,7 +435,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma) case _DRM_FRAME_BUFFER: case _DRM_REGISTERS: if (VM_OFFSET(vma) >= __pa(high_memory)) { -#if defined(__i386__) +#if defined(__i386__) || defined(__x86_64__) if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) { pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT; diff --git a/linux-core/i810_dma.c b/linux-core/i810_dma.c index f4eef3a3..13f5f64f 100644 --- a/linux-core/i810_dma.c +++ b/linux-core/i810_dma.c @@ -26,7 +26,7 @@ * * Authors: Rickard E. (Rik) Faith <faith@valinux.com> * Jeff Hartmann <jhartmann@valinux.com> - * Keith Whitwell <keith_whitwell@yahoo.com> + * Keith Whitwell <keith@tungstengraphics.com> * */ @@ -39,6 +39,12 @@ #include <linux/interrupt.h> /* For task queue support */ #include <linux/delay.h> +#ifdef DO_MUNMAP_4_ARGS +#define DO_MUNMAP(m, a, l) do_munmap(m, a, l, 1) +#else +#define DO_MUNMAP(m, a, l) do_munmap(m, a, l) +#endif + #define I810_BUF_FREE 2 #define I810_BUF_CLIENT 1 #define I810_BUF_HARDWARE 0 @@ -218,7 +224,7 @@ static int i810_unmap_buffer(drm_buf_t *buf) #else down_write( ¤t->mm->mmap_sem ); #endif - retcode = do_munmap(current->mm, + retcode = DO_MUNMAP(current->mm, (unsigned long)buf_priv->virtual, (size_t) buf->total); #if LINUX_VERSION_CODE <= 0x020402 @@ -263,44 +269,6 @@ static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d, return retcode; } -static unsigned long i810_alloc_page(drm_device_t *dev) -{ - unsigned long address; - - address = __get_free_page(GFP_KERNEL); - if(address == 0UL) - return 0; - -#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 < 0x020409 - atomic_dec(&virt_to_page(page)->count); - clear_bit(PG_locked, &virt_to_page(page)->flags); - wake_up(&virt_to_page(page)->wait); -#else - struct page *p = virt_to_page(page); - put_page(p); - unlock_page(p); -#endif - free_page(page); - } -} - static int i810_dma_cleanup(drm_device_t *dev) { drm_device_dma_t *dma = dev->dma; @@ -315,7 +283,9 @@ static int i810_dma_cleanup(drm_device_t *dev) dev_priv->ring.Size); } if(dev_priv->hw_status_page != 0UL) { - i810_free_page(dev, dev_priv->hw_status_page); + pci_free_consistent(dev->pdev, PAGE_SIZE, + (void *)dev_priv->hw_status_page, + dev_priv->dma_status_page); /* Need to rewrite hardware status page */ I810_WRITE(0x02080, 0x1ffff000); } @@ -475,7 +445,9 @@ static int i810_dma_initialize(drm_device_t *dev, dev_priv->zi1 = init->depth_offset | init->pitch_bits; /* Program Hardware Status Page */ - dev_priv->hw_status_page = i810_alloc_page(dev); + dev_priv->hw_status_page = + (unsigned long) pci_alloc_consistent(dev->pdev, PAGE_SIZE, + &dev_priv->dma_status_page); if(dev_priv->hw_status_page == 0UL) { dev->dev_private = (void *)dev_priv; i810_dma_cleanup(dev); @@ -485,7 +457,7 @@ static int i810_dma_initialize(drm_device_t *dev, memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE); DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page); - I810_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page)); + I810_WRITE(0x02080, dev_priv->dma_status_page); DRM_DEBUG("Enabled hardware status page\n"); /* Now we need to init our freelist */ diff --git a/linux-core/i810_drv.h b/linux-core/i810_drv.h index 99165cf8..106abf56 100644 --- a/linux-core/i810_drv.h +++ b/linux-core/i810_drv.h @@ -64,6 +64,8 @@ typedef struct drm_i810_private { unsigned long hw_status_page; unsigned long counter; + dma_addr_t dma_status_page; + drm_buf_t *mmap_buffer; diff --git a/linux-core/i830_dma.c b/linux-core/i830_dma.c index 70884373..d29e21cb 100644 --- a/linux-core/i830_dma.c +++ b/linux-core/i830_dma.c @@ -272,29 +272,6 @@ static int i830_dma_get_buffer(drm_device_t *dev, drm_i830_dma_t *d, return retcode; } -static unsigned long i830_alloc_page(drm_device_t *dev) -{ - unsigned long address; - - address = __get_free_page(GFP_KERNEL); - if(address == 0UL) - return 0; - - get_page(virt_to_page(address)); - LockPage(virt_to_page(address)); - return address; -} - -static void i830_free_page(drm_device_t *dev, unsigned long page) -{ - if (page) { - struct page *p = virt_to_page(page); - put_page(p); - UnlockPage(p); - free_page(page); - } -} - static int i830_dma_cleanup(drm_device_t *dev) { drm_device_dma_t *dma = dev->dma; @@ -309,7 +286,9 @@ static int i830_dma_cleanup(drm_device_t *dev) dev_priv->ring.Size); } if(dev_priv->hw_status_page != 0UL) { - i830_free_page(dev, dev_priv->hw_status_page); + pci_free_consistent(dev->pdev, PAGE_SIZE, + (void *)dev_priv->hw_status_page, + dev_priv->dma_status_page); /* Need to rewrite hardware status page */ I830_WRITE(0x02080, 0x1ffff000); } @@ -483,7 +462,9 @@ static int i830_dma_initialize(drm_device_t *dev, dev_priv->depth_pitch = init->depth_pitch; /* Program Hardware Status Page */ - dev_priv->hw_status_page = i830_alloc_page(dev); + dev_priv->hw_status_page = + (unsigned long) pci_alloc_consistent(dev->pdev, PAGE_SIZE, + &dev_priv->dma_status_page); if(dev_priv->hw_status_page == 0UL) { dev->dev_private = (void *)dev_priv; i830_dma_cleanup(dev); @@ -493,7 +474,7 @@ static int i830_dma_initialize(drm_device_t *dev, memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE); DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page); - I830_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page)); + I830_WRITE(0x02080, dev_priv->dma_status_page); DRM_DEBUG("Enabled hardware status page\n"); /* Now we need to init our freelist */ diff --git a/linux-core/i830_drv.h b/linux-core/i830_drv.h index 527d0ce3..eec640ca 100644 --- a/linux-core/i830_drv.h +++ b/linux-core/i830_drv.h @@ -64,6 +64,8 @@ typedef struct drm_i830_private { unsigned long hw_status_page; unsigned long counter; + dma_addr_t dma_status_page; + drm_buf_t *mmap_buffer; u32 front_di1, back_di1, zi1; diff --git a/linux/Makefile.linux b/linux/Makefile.linux index 7c3f1db9..4505e6c1 100644 --- a/linux/Makefile.linux +++ b/linux/Makefile.linux @@ -44,7 +44,7 @@ LIBS = DRMTEMPLATES = drm_auth.h drm_bufs.h drm_context.h drm_dma.h drm_drawable.h \ drm_drv.h drm_fops.h drm_init.h drm_ioctl.h drm_lists.h \ drm_lock.h drm_memory.h drm_proc.h drm_stub.h drm_vm.h -DRMHEADERS = drm.h drmP.h +DRMHEADERS = drm.h drmP.h drm_sarea.h GAMMAOBJS = gamma_drv.o gamma_dma.o GAMMAHEADERS = gamma_drv.h $(DRMHEADERS) $(DRMTEMPLATES) @@ -52,7 +52,7 @@ GAMMAHEADERS = gamma_drv.h $(DRMHEADERS) $(DRMTEMPLATES) TDFXOBJS = tdfx_drv.o TDFXHEADERS = tdfx.h $(DRMHEADERS) $(DRMTEMPLATES) -R128OBJS = r128_drv.o r128_cce.o r128_state.o +R128OBJS = r128_drv.o r128_cce.o r128_state.o r128_irq.o 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 @@ -158,7 +158,7 @@ MODS += i810.o MODS += i830.o endif -MGAOBJS = mga_drv.o mga_dma.o mga_state.o mga_warp.o +MGAOBJS = mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o MGAHEADERS = mga.h mga_drv.h mga_drm.h $(DRMHEADERS) $(DRMTEMPLATES) I810OBJS = i810_drv.o i810_dma.o diff --git a/linux/drm_vm.h b/linux/drm_vm.h index 52dfd594..683c0857 100644 --- a/linux/drm_vm.h +++ b/linux/drm_vm.h @@ -71,7 +71,7 @@ struct page *DRM(vm_nopage)(struct vm_area_struct *vma, * Find the right map */ - if(!dev->agp->cant_use_aperture) goto vm_nopage_error; + if(!dev->agp || !dev->agp->cant_use_aperture) goto vm_nopage_error; list_for_each(list, &dev->maplist->head) { r_list = (drm_map_list_t *)list; @@ -408,7 +408,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma) if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) { vma->vm_flags &= VM_MAYWRITE; -#if defined(__i386__) +#if defined(__i386__) || defined(__x86_64__) pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW; #else /* Ye gads this is ugly. With more thought @@ -435,7 +435,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma) case _DRM_FRAME_BUFFER: case _DRM_REGISTERS: if (VM_OFFSET(vma) >= __pa(high_memory)) { -#if defined(__i386__) +#if defined(__i386__) || defined(__x86_64__) if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) { pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT; diff --git a/linux/i810_dma.c b/linux/i810_dma.c index f4eef3a3..13f5f64f 100644 --- a/linux/i810_dma.c +++ b/linux/i810_dma.c @@ -26,7 +26,7 @@ * * Authors: Rickard E. (Rik) Faith <faith@valinux.com> * Jeff Hartmann <jhartmann@valinux.com> - * Keith Whitwell <keith_whitwell@yahoo.com> + * Keith Whitwell <keith@tungstengraphics.com> * */ @@ -39,6 +39,12 @@ #include <linux/interrupt.h> /* For task queue support */ #include <linux/delay.h> +#ifdef DO_MUNMAP_4_ARGS +#define DO_MUNMAP(m, a, l) do_munmap(m, a, l, 1) +#else +#define DO_MUNMAP(m, a, l) do_munmap(m, a, l) +#endif + #define I810_BUF_FREE 2 #define I810_BUF_CLIENT 1 #define I810_BUF_HARDWARE 0 @@ -218,7 +224,7 @@ static int i810_unmap_buffer(drm_buf_t *buf) #else down_write( ¤t->mm->mmap_sem ); #endif - retcode = do_munmap(current->mm, + retcode = DO_MUNMAP(current->mm, (unsigned long)buf_priv->virtual, (size_t) buf->total); #if LINUX_VERSION_CODE <= 0x020402 @@ -263,44 +269,6 @@ static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d, return retcode; } -static unsigned long i810_alloc_page(drm_device_t *dev) -{ - unsigned long address; - - address = __get_free_page(GFP_KERNEL); - if(address == 0UL) - return 0; - -#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 < 0x020409 - atomic_dec(&virt_to_page(page)->count); - clear_bit(PG_locked, &virt_to_page(page)->flags); - wake_up(&virt_to_page(page)->wait); -#else - struct page *p = virt_to_page(page); - put_page(p); - unlock_page(p); -#endif - free_page(page); - } -} - static int i810_dma_cleanup(drm_device_t *dev) { drm_device_dma_t *dma = dev->dma; @@ -315,7 +283,9 @@ static int i810_dma_cleanup(drm_device_t *dev) dev_priv->ring.Size); } if(dev_priv->hw_status_page != 0UL) { - i810_free_page(dev, dev_priv->hw_status_page); + pci_free_consistent(dev->pdev, PAGE_SIZE, + (void *)dev_priv->hw_status_page, + dev_priv->dma_status_page); /* Need to rewrite hardware status page */ I810_WRITE(0x02080, 0x1ffff000); } @@ -475,7 +445,9 @@ static int i810_dma_initialize(drm_device_t *dev, dev_priv->zi1 = init->depth_offset | init->pitch_bits; /* Program Hardware Status Page */ - dev_priv->hw_status_page = i810_alloc_page(dev); + dev_priv->hw_status_page = + (unsigned long) pci_alloc_consistent(dev->pdev, PAGE_SIZE, + &dev_priv->dma_status_page); if(dev_priv->hw_status_page == 0UL) { dev->dev_private = (void *)dev_priv; i810_dma_cleanup(dev); @@ -485,7 +457,7 @@ static int i810_dma_initialize(drm_device_t *dev, memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE); DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page); - I810_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page)); + I810_WRITE(0x02080, dev_priv->dma_status_page); DRM_DEBUG("Enabled hardware status page\n"); /* Now we need to init our freelist */ diff --git a/linux/i810_drv.h b/linux/i810_drv.h index 99165cf8..106abf56 100644 --- a/linux/i810_drv.h +++ b/linux/i810_drv.h @@ -64,6 +64,8 @@ typedef struct drm_i810_private { unsigned long hw_status_page; unsigned long counter; + dma_addr_t dma_status_page; + drm_buf_t *mmap_buffer; diff --git a/linux/i830_dma.c b/linux/i830_dma.c index 70884373..d29e21cb 100644 --- a/linux/i830_dma.c +++ b/linux/i830_dma.c @@ -272,29 +272,6 @@ static int i830_dma_get_buffer(drm_device_t *dev, drm_i830_dma_t *d, return retcode; } -static unsigned long i830_alloc_page(drm_device_t *dev) -{ - unsigned long address; - - address = __get_free_page(GFP_KERNEL); - if(address == 0UL) - return 0; - - get_page(virt_to_page(address)); - LockPage(virt_to_page(address)); - return address; -} - -static void i830_free_page(drm_device_t *dev, unsigned long page) -{ - if (page) { - struct page *p = virt_to_page(page); - put_page(p); - UnlockPage(p); - free_page(page); - } -} - static int i830_dma_cleanup(drm_device_t *dev) { drm_device_dma_t *dma = dev->dma; @@ -309,7 +286,9 @@ static int i830_dma_cleanup(drm_device_t *dev) dev_priv->ring.Size); } if(dev_priv->hw_status_page != 0UL) { - i830_free_page(dev, dev_priv->hw_status_page); + pci_free_consistent(dev->pdev, PAGE_SIZE, + (void *)dev_priv->hw_status_page, + dev_priv->dma_status_page); /* Need to rewrite hardware status page */ I830_WRITE(0x02080, 0x1ffff000); } @@ -483,7 +462,9 @@ static int i830_dma_initialize(drm_device_t *dev, dev_priv->depth_pitch = init->depth_pitch; /* Program Hardware Status Page */ - dev_priv->hw_status_page = i830_alloc_page(dev); + dev_priv->hw_status_page = + (unsigned long) pci_alloc_consistent(dev->pdev, PAGE_SIZE, + &dev_priv->dma_status_page); if(dev_priv->hw_status_page == 0UL) { dev->dev_private = (void *)dev_priv; i830_dma_cleanup(dev); @@ -493,7 +474,7 @@ static int i830_dma_initialize(drm_device_t *dev, memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE); DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page); - I830_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page)); + I830_WRITE(0x02080, dev_priv->dma_status_page); DRM_DEBUG("Enabled hardware status page\n"); /* Now we need to init our freelist */ diff --git a/linux/i830_drv.h b/linux/i830_drv.h index 527d0ce3..eec640ca 100644 --- a/linux/i830_drv.h +++ b/linux/i830_drv.h @@ -64,6 +64,8 @@ typedef struct drm_i830_private { unsigned long hw_status_page; unsigned long counter; + dma_addr_t dma_status_page; + drm_buf_t *mmap_buffer; u32 front_di1, back_di1, zi1; diff --git a/shared-core/drm_sarea.h b/shared-core/drm_sarea.h new file mode 100644 index 00000000..cee48eee --- /dev/null +++ b/shared-core/drm_sarea.h @@ -0,0 +1,57 @@ +/* sarea.h -- SAREA definitions -*- linux-c -*- + * + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * 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 + * TUNGSTEN GRAPHICS 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: + * Michel Dänzer <michel@daenzer.net> + */ + +#ifndef _DRM_SAREA_H_ +#define _DRM_SAREA_H_ + +#define SAREA_MAX_DRAWABLES 256 + +typedef struct _drm_sarea_drawable_t { + unsigned int stamp; + unsigned int flags; +} drm_sarea_drawable_t; + +typedef struct _dri_sarea_frame_t { + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; + unsigned int fullscreen; +} drm_sarea_frame_t; + +typedef struct _drm_sarea_t { + /* first thing is always the drm locking structure */ + drm_hw_lock_t lock; + /* NOT_DONE: Use readers/writer lock for drawable_lock */ + drm_hw_lock_t drawable_lock; + drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; + drm_sarea_frame_t frame; + drm_context_t dummy_context; +} drm_sarea_t; + +#endif /* _DRM_SAREA_H_ */ diff --git a/shared-core/mga_dma.c b/shared-core/mga_dma.c index 3c84de63..22bd61f0 100644 --- a/shared-core/mga_dma.c +++ b/shared-core/mga_dma.c @@ -27,7 +27,7 @@ * Authors: * Rickard E. (Rik) Faith <faith@valinux.com> * Jeff Hartmann <jhartmann@valinux.com> - * Keith Whitwell <keithw@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> * * Rewritten by: * Gareth Hughes <gareth@valinux.com> @@ -166,7 +166,7 @@ void mga_do_dma_flush( drm_mga_private_t *dev_priv ) for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK; if ( status == MGA_ENDPRDMASTS ) break; - udelay( 1 ); + DRM_UDELAY( 1 ); } if ( primary->tail == primary->last_flush ) { diff --git a/shared-core/mga_drm.h b/shared-core/mga_drm.h index 8f56beed..b19bc011 100644 --- a/shared-core/mga_drm.h +++ b/shared-core/mga_drm.h @@ -26,7 +26,7 @@ * * Authors: * Jeff Hartmann <jhartmann@valinux.com> - * Keith Whitwell <keithw@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> * * Rewritten by: * Gareth Hughes <gareth@valinux.com> @@ -239,6 +239,7 @@ typedef struct _drm_mga_sarea { #define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t) #define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x47, drm_mga_iload_t) #define DRM_IOCTL_MGA_BLIT DRM_IOW( 0x48, drm_mga_blit_t) +#define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(0x49, drm_mga_getparam_t) typedef struct _drm_mga_warp_index { int installed; @@ -322,4 +323,14 @@ typedef struct _drm_mga_blit { int source_pitch, dest_pitch; } drm_mga_blit_t; +/* 3.1: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define MGA_PARAM_IRQ_NR 1 + +typedef struct drm_mga_getparam { + int param; + int *value; +} drm_mga_getparam_t; + #endif diff --git a/shared-core/mga_drv.h b/shared-core/mga_drv.h index b5f16ae2..a5085b06 100644 --- a/shared-core/mga_drv.h +++ b/shared-core/mga_drv.h @@ -125,6 +125,7 @@ extern int mga_dma_vertex( DRM_IOCTL_ARGS ); extern int mga_dma_indices( DRM_IOCTL_ARGS ); extern int mga_dma_iload( DRM_IOCTL_ARGS ); extern int mga_dma_blit( DRM_IOCTL_ARGS ); +extern int mga_getparam( DRM_IOCTL_ARGS ); /* mga_warp.c */ extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv ); @@ -141,6 +142,7 @@ extern int mga_warp_init( drm_mga_private_t *dev_priv ); #ifdef __alpha__ #define MGA_READ( reg ) (_MGA_READ((u32 *)MGA_ADDR(reg))) +#define MGA_READ8( reg ) (_MGA_READ((u8 *)MGA_ADDR(reg))) #define MGA_WRITE( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF( reg ) = val; } while (0) #define MGA_WRITE8( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8( reg ) = val; } while (0) @@ -152,6 +154,7 @@ static inline u32 _MGA_READ(u32 *addr) #else #define MGA_READ( reg ) MGA_DEREF( reg ) +#define MGA_READ8( reg ) MGA_DEREF8( reg ) #define MGA_WRITE( reg, val ) do { MGA_DEREF( reg ) = val; } while (0) #define MGA_WRITE8( reg, val ) do { MGA_DEREF8( reg ) = val; } while (0) #endif @@ -345,6 +348,11 @@ do { \ /* A reduced set of the mga registers. */ #define MGA_CRTC_INDEX 0x1fd4 +#define MGA_CRTC_DATA 0x1fd5 + +/* CRTC11 */ +#define MGA_VINTCLR (1 << 4) +#define MGA_VINTEN (1 << 5) #define MGA_ALPHACTRL 0x2c7c #define MGA_AR0 0x1c60 @@ -416,8 +424,10 @@ do { \ #define MGA_ICLEAR 0x1e18 # define MGA_SOFTRAPICLR (1 << 0) +# define MGA_VLINEICLR (1 << 5) #define MGA_IEN 0x1e1c # define MGA_SOFTRAPIEN (1 << 0) +# define MGA_VLINEIEN (1 << 5) #define MGA_LEN 0x1c5c @@ -456,6 +466,8 @@ do { \ # define MGA_SRCACC_AGP (1 << 1) #define MGA_STATUS 0x1e14 # define MGA_SOFTRAPEN (1 << 0) +# define MGA_VSYNCPEN (1 << 4) +# define MGA_VLINEPEN (1 << 5) # define MGA_DWGENGSTS (1 << 16) # define MGA_ENDPRDMASTS (1 << 17) #define MGA_STENCIL 0x2cc8 diff --git a/shared-core/mga_irq.c b/shared-core/mga_irq.c new file mode 100644 index 00000000..568d193f --- /dev/null +++ b/shared-core/mga_irq.c @@ -0,0 +1,99 @@ +/* mga_irq.c -- IRQ handling for radeon -*- linux-c -*- + * + * Copyright (C) The Weather Channel, Inc. 2002. 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 + * PRECISION INSIGHT 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> + */ + +#include "mga.h" +#include "drmP.h" +#include "drm.h" +#include "mga_drm.h" +#include "mga_drv.h" + +void mga_dma_service( DRM_IRQ_ARGS ) +{ + drm_device_t *dev = (drm_device_t *) arg; + drm_mga_private_t *dev_priv = + (drm_mga_private_t *)dev->dev_private; + int status; + + status = MGA_READ( MGA_STATUS ); + + /* VBLANK interrupt */ + if ( status & MGA_VLINEPEN ) { + MGA_WRITE( MGA_ICLEAR, MGA_VLINEICLR ); + atomic_inc(&dev->vbl_received); + DRM_WAKEUP(&dev->vbl_queue); + } +} + +int mga_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 ) <= (1<<23) ) ); + + *sequence = cur_vblank; + + return ret; +} + +void mga_driver_irq_preinstall( drm_device_t *dev ) { + drm_mga_private_t *dev_priv = + (drm_mga_private_t *)dev->dev_private; + + /* Disable *all* interrupts */ + MGA_WRITE( MGA_IEN, 0 ); + /* Clear bits if they're already high */ + MGA_WRITE( MGA_ICLEAR, ~0 ); +} + +void mga_driver_irq_postinstall( drm_device_t *dev ) { + drm_mga_private_t *dev_priv = + (drm_mga_private_t *)dev->dev_private; + + /* Turn on VBL interrupt */ + MGA_WRITE( MGA_IEN, MGA_VLINEIEN ); +} + +void mga_driver_irq_uninstall( drm_device_t *dev ) { + drm_mga_private_t *dev_priv = + (drm_mga_private_t *)dev->dev_private; + if ( dev_priv ) { + /* Disable *all* interrupts */ + MGA_WRITE( MGA_IEN, 0 ); + } +} diff --git a/shared-core/mga_state.c b/shared-core/mga_state.c index 5e5b594a..61077220 100644 --- a/shared-core/mga_state.c +++ b/shared-core/mga_state.c @@ -26,7 +26,7 @@ * * Authors: * Jeff Hartmann <jhartmann@valinux.com> - * Keith Whitwell <keithw@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> * * Rewritten by: * Gareth Hughes <gareth@valinux.com> @@ -1075,3 +1075,36 @@ int mga_dma_blit( DRM_IOCTL_ARGS ) return 0; } + +int mga_getparam( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_mga_private_t *dev_priv = dev->dev_private; + drm_mga_getparam_t param; + int value; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL( param, (drm_mga_getparam_t *)data, + sizeof(param) ); + + DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID ); + + switch( param.param ) { + case MGA_PARAM_IRQ_NR: + value = dev->irq; + break; + default: + return DRM_ERR(EINVAL); + } + + if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return DRM_ERR(EFAULT); + } + + return 0; +} diff --git a/shared-core/r128_drm.h b/shared-core/r128_drm.h index a8d23008..bbb1a93b 100644 --- a/shared-core/r128_drm.h +++ b/shared-core/r128_drm.h @@ -190,6 +190,7 @@ typedef struct drm_r128_sarea { #define DRM_IOCTL_R128_INDIRECT DRM_IOWR(0x4f, drm_r128_indirect_t) #define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( 0x50, drm_r128_fullscreen_t) #define DRM_IOCTL_R128_CLEAR2 DRM_IOW( 0x51, drm_r128_clear2_t) +#define DRM_IOCTL_R128_GETPARAM DRM_IOW( 0x52, drm_r128_getparam_t) typedef struct drm_r128_init { enum { @@ -305,4 +306,14 @@ typedef struct drm_r128_fullscreen { } func; } drm_r128_fullscreen_t; +/* 2.3: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define R128_PARAM_IRQ_NR 1 + +typedef struct drm_r128_getparam { + int param; + int *value; +} drm_r128_getparam_t; + #endif diff --git a/shared-core/r128_drv.h b/shared-core/r128_drv.h index aeb73e08..763fcb3a 100644 --- a/shared-core/r128_drv.h +++ b/shared-core/r128_drv.h @@ -124,6 +124,7 @@ extern int r128_cce_idle( DRM_IOCTL_ARGS ); extern int r128_engine_reset( DRM_IOCTL_ARGS ); extern int r128_fullscreen( DRM_IOCTL_ARGS ); extern int r128_cce_buffers( DRM_IOCTL_ARGS ); +extern int r128_getparam( DRM_IOCTL_ARGS ); extern void r128_freelist_reset( drm_device_t *dev ); extern drm_buf_t *r128_freelist_get( drm_device_t *dev ); @@ -213,6 +214,11 @@ extern int r128_cce_indirect( DRM_IOCTL_ARGS ); #define R128_DST_PITCH_OFFSET_C 0x1c80 # define R128_DST_TILE (1 << 31) +#define R128_GEN_INT_CNTL 0x0040 +# define R128_CRTC_VBLANK_INT_EN (1 << 0) +#define R128_GEN_INT_STATUS 0x0044 +# define R128_CRTC_VBLANK_INT (1 << 0) +# define R128_CRTC_VBLANK_INT_AK (1 << 0) #define R128_GEN_RESET_CNTL 0x00f0 # define R128_SOFT_RESET_GUI (1 << 0) diff --git a/shared-core/r128_irq.c b/shared-core/r128_irq.c new file mode 100644 index 00000000..a29a81b5 --- /dev/null +++ b/shared-core/r128_irq.c @@ -0,0 +1,99 @@ +/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*- + * + * Copyright (C) The Weather Channel, Inc. 2002. 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 + * PRECISION INSIGHT 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> + */ + +#include "r128.h" +#include "drmP.h" +#include "drm.h" +#include "r128_drm.h" +#include "r128_drv.h" + +void r128_dma_service( DRM_IRQ_ARGS ) +{ + drm_device_t *dev = (drm_device_t *) arg; + drm_r128_private_t *dev_priv = + (drm_r128_private_t *)dev->dev_private; + int status; + + status = R128_READ( R128_GEN_INT_STATUS ); + + /* VBLANK interrupt */ + if ( status & R128_CRTC_VBLANK_INT ) { + R128_WRITE( R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK ); + atomic_inc(&dev->vbl_received); + DRM_WAKEUP(&dev->vbl_queue); + } +} + +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 ) <= (1<<23) ) ); + + *sequence = cur_vblank; + + return ret; +} + +void r128_driver_irq_preinstall( drm_device_t *dev ) { + drm_r128_private_t *dev_priv = + (drm_r128_private_t *)dev->dev_private; + + /* Disable *all* interrupts */ + R128_WRITE( R128_GEN_INT_CNTL, 0 ); + /* Clear vblank bit if it's already high */ + R128_WRITE( R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK ); +} + +void r128_driver_irq_postinstall( drm_device_t *dev ) { + drm_r128_private_t *dev_priv = + (drm_r128_private_t *)dev->dev_private; + + /* Turn on VBL interrupt */ + R128_WRITE( R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN ); +} + +void r128_driver_irq_uninstall( drm_device_t *dev ) { + drm_r128_private_t *dev_priv = + (drm_r128_private_t *)dev->dev_private; + if ( dev_priv ) { + /* Disable *all* interrupts */ + R128_WRITE( R128_GEN_INT_CNTL, 0 ); + } +} diff --git a/shared-core/r128_state.c b/shared-core/r128_state.c index 6ae58639..68f73061 100644 --- a/shared-core/r128_state.c +++ b/shared-core/r128_state.c @@ -1564,3 +1564,36 @@ int r128_cce_indirect( DRM_IOCTL_ARGS ) return 0; } + +int r128_getparam( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_getparam_t param; + int value; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL( param, (drm_r128_getparam_t *)data, + sizeof(param) ); + + DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID ); + + switch( param.param ) { + case R128_PARAM_IRQ_NR: + value = dev->irq; + break; + default: + return DRM_ERR(EINVAL); + } + + if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return DRM_ERR(EFAULT); + } + + return 0; +} diff --git a/shared-core/radeon_drm.h b/shared-core/radeon_drm.h index 91b395c3..f05507e2 100644 --- a/shared-core/radeon_drm.h +++ b/shared-core/radeon_drm.h @@ -27,7 +27,7 @@ * Authors: * Kevin E. Martin <martin@valinux.com> * Gareth Hughes <gareth@valinux.com> - * Keith Whitwell <keith_whitwell@yahoo.com> + * Keith Whitwell <keith@tungstengraphics.com> */ #ifndef __RADEON_DRM_H__ @@ -355,6 +355,7 @@ typedef struct { int ctx_owner; int pfState; /* number of 3d windows (0,1,2ormore) */ int pfCurrentPage; /* which buffer is being displayed? */ + int crtc2_base; /* CRTC2 frame offset */ } drm_radeon_sarea_t; diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 81615a78..65f3c926 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -109,8 +109,6 @@ typedef struct drm_radeon_private { int do_boxes; int page_flipping; int current_page; - u32 crtc_offset; - u32 crtc_offset_cntl; u32 color_fmt; unsigned int front_offset; @@ -230,6 +228,8 @@ extern int radeon_emit_irq(drm_device_t *dev); #define RADEON_CRTC_OFFSET_CNTL 0x0228 # define RADEON_CRTC_TILE_EN (1 << 15) # define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16) +#define RADEON_CRTC2_OFFSET 0x0324 +#define RADEON_CRTC2_OFFSET_CNTL 0x0328 #define RADEON_RB3D_COLORPITCH 0x1c48 diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index b4d66524..7b480a7e 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -30,6 +30,7 @@ #include "radeon.h" #include "drmP.h" #include "drm.h" +#include "drm_sarea.h" #include "radeon_drm.h" #include "radeon_drv.h" @@ -803,6 +804,9 @@ static void radeon_cp_dispatch_swap( drm_device_t *dev ) static void radeon_cp_dispatch_flip( drm_device_t *dev ) { drm_radeon_private_t *dev_priv = dev->dev_private; + drm_sarea_t *sarea = (drm_sarea_t *)dev_priv->sarea->handle; + int offset = (dev_priv->current_page == 1) + ? dev_priv->front_offset : dev_priv->back_offset; RING_LOCALS; DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n", __FUNCTION__, @@ -816,18 +820,17 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev ) radeon_cp_performance_boxes( dev_priv ); } - BEGIN_RING( 4 ); + /* Update the frame offsets for both CRTCs + */ + BEGIN_RING( 6 ); RADEON_WAIT_UNTIL_3D_IDLE(); - OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET, 0 ) ); - - if ( dev_priv->current_page == 0 ) { - OUT_RING( dev_priv->back_offset ); - dev_priv->current_page = 1; - } else { - OUT_RING( dev_priv->front_offset ); - dev_priv->current_page = 0; - } + OUT_RING_REG( RADEON_CRTC_OFFSET, ( ( sarea->frame.y * dev_priv->front_pitch + + sarea->frame.x + * ( dev_priv->color_fmt - 2 ) ) & ~7 ) + + offset ); + OUT_RING_REG( RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base + + offset ); ADVANCE_RING(); @@ -836,7 +839,8 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev ) * performing the swapbuffer ioctl. */ dev_priv->sarea_priv->last_frame++; - dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page; + dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page = + 1 - dev_priv->current_page; BEGIN_RING( 2 ); @@ -1304,12 +1308,12 @@ static int radeon_do_init_pageflip( drm_device_t *dev ) DRM_DEBUG( "\n" ); - dev_priv->crtc_offset_cntl = RADEON_READ( RADEON_CRTC_OFFSET_CNTL ); - - BEGIN_RING( 4 ); + BEGIN_RING( 6 ); RADEON_WAIT_UNTIL_3D_IDLE(); OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET_CNTL, 0 ) ); - OUT_RING( dev_priv->crtc_offset_cntl | RADEON_CRTC_OFFSET_FLIP_CNTL ); + OUT_RING( RADEON_READ( RADEON_CRTC_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL ); + OUT_RING( CP_PACKET0( RADEON_CRTC2_OFFSET_CNTL, 0 ) ); + OUT_RING( RADEON_READ( RADEON_CRTC2_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL ); ADVANCE_RING(); dev_priv->page_flipping = 1; @@ -1330,10 +1334,6 @@ int radeon_do_cleanup_pageflip( drm_device_t *dev ) if (dev_priv->current_page != 0) radeon_cp_dispatch_flip( dev ); - /* FIXME: If the X server changes screen resolution, it - * clobbers the value of RADEON_CRTC_OFFSET_CNTL, above, - * leading to a flashing efect. - */ dev_priv->page_flipping = 0; return 0; } diff --git a/shared/drm_sarea.h b/shared/drm_sarea.h new file mode 100644 index 00000000..cee48eee --- /dev/null +++ b/shared/drm_sarea.h @@ -0,0 +1,57 @@ +/* sarea.h -- SAREA definitions -*- linux-c -*- + * + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * 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 + * TUNGSTEN GRAPHICS 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: + * Michel Dänzer <michel@daenzer.net> + */ + +#ifndef _DRM_SAREA_H_ +#define _DRM_SAREA_H_ + +#define SAREA_MAX_DRAWABLES 256 + +typedef struct _drm_sarea_drawable_t { + unsigned int stamp; + unsigned int flags; +} drm_sarea_drawable_t; + +typedef struct _dri_sarea_frame_t { + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; + unsigned int fullscreen; +} drm_sarea_frame_t; + +typedef struct _drm_sarea_t { + /* first thing is always the drm locking structure */ + drm_hw_lock_t lock; + /* NOT_DONE: Use readers/writer lock for drawable_lock */ + drm_hw_lock_t drawable_lock; + drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; + drm_sarea_frame_t frame; + drm_context_t dummy_context; +} drm_sarea_t; + +#endif /* _DRM_SAREA_H_ */ diff --git a/shared/mga.h b/shared/mga.h index 5380cb0d..49530442 100644 --- a/shared/mga.h +++ b/shared/mga.h @@ -45,11 +45,11 @@ #define DRIVER_NAME "mga" #define DRIVER_DESC "Matrox G200/G400" -#define DRIVER_DATE "20010321" +#define DRIVER_DATE "20021029" #define DRIVER_MAJOR 3 -#define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 2 +#define DRIVER_MINOR 1 +#define DRIVER_PATCHLEVEL 0 #define DRIVER_IOCTLS \ [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { mga_dma_buffers, 1, 0 }, \ @@ -61,7 +61,8 @@ [DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)] = { mga_dma_vertex, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_MGA_INDICES)] = { mga_dma_indices, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)] = { mga_dma_iload, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MGA_BLIT)] = { mga_dma_blit, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_MGA_BLIT)] = { mga_dma_blit, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MGA_GETPARAM)]= { mga_getparam, 1, 0 }, #define __HAVE_COUNTERS 3 #define __HAVE_COUNTER6 _DRM_STAT_IRQ @@ -77,6 +78,9 @@ /* DMA customization: */ #define __HAVE_DMA 1 +#define __HAVE_DMA_IRQ 1 +#define __HAVE_VBL_IRQ 1 +#define __HAVE_SHARED_IRQ 1 #define __HAVE_DMA_QUIESCENT 1 #define DRIVER_DMA_QUIESCENT() do { \ diff --git a/shared/mga_dma.c b/shared/mga_dma.c index 3c84de63..22bd61f0 100644 --- a/shared/mga_dma.c +++ b/shared/mga_dma.c @@ -27,7 +27,7 @@ * Authors: * Rickard E. (Rik) Faith <faith@valinux.com> * Jeff Hartmann <jhartmann@valinux.com> - * Keith Whitwell <keithw@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> * * Rewritten by: * Gareth Hughes <gareth@valinux.com> @@ -166,7 +166,7 @@ void mga_do_dma_flush( drm_mga_private_t *dev_priv ) for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK; if ( status == MGA_ENDPRDMASTS ) break; - udelay( 1 ); + DRM_UDELAY( 1 ); } if ( primary->tail == primary->last_flush ) { diff --git a/shared/mga_drm.h b/shared/mga_drm.h index 8f56beed..b19bc011 100644 --- a/shared/mga_drm.h +++ b/shared/mga_drm.h @@ -26,7 +26,7 @@ * * Authors: * Jeff Hartmann <jhartmann@valinux.com> - * Keith Whitwell <keithw@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> * * Rewritten by: * Gareth Hughes <gareth@valinux.com> @@ -239,6 +239,7 @@ typedef struct _drm_mga_sarea { #define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t) #define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x47, drm_mga_iload_t) #define DRM_IOCTL_MGA_BLIT DRM_IOW( 0x48, drm_mga_blit_t) +#define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(0x49, drm_mga_getparam_t) typedef struct _drm_mga_warp_index { int installed; @@ -322,4 +323,14 @@ typedef struct _drm_mga_blit { int source_pitch, dest_pitch; } drm_mga_blit_t; +/* 3.1: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define MGA_PARAM_IRQ_NR 1 + +typedef struct drm_mga_getparam { + int param; + int *value; +} drm_mga_getparam_t; + #endif diff --git a/shared/mga_drv.h b/shared/mga_drv.h index b5f16ae2..a5085b06 100644 --- a/shared/mga_drv.h +++ b/shared/mga_drv.h @@ -125,6 +125,7 @@ extern int mga_dma_vertex( DRM_IOCTL_ARGS ); extern int mga_dma_indices( DRM_IOCTL_ARGS ); extern int mga_dma_iload( DRM_IOCTL_ARGS ); extern int mga_dma_blit( DRM_IOCTL_ARGS ); +extern int mga_getparam( DRM_IOCTL_ARGS ); /* mga_warp.c */ extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv ); @@ -141,6 +142,7 @@ extern int mga_warp_init( drm_mga_private_t *dev_priv ); #ifdef __alpha__ #define MGA_READ( reg ) (_MGA_READ((u32 *)MGA_ADDR(reg))) +#define MGA_READ8( reg ) (_MGA_READ((u8 *)MGA_ADDR(reg))) #define MGA_WRITE( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF( reg ) = val; } while (0) #define MGA_WRITE8( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8( reg ) = val; } while (0) @@ -152,6 +154,7 @@ static inline u32 _MGA_READ(u32 *addr) #else #define MGA_READ( reg ) MGA_DEREF( reg ) +#define MGA_READ8( reg ) MGA_DEREF8( reg ) #define MGA_WRITE( reg, val ) do { MGA_DEREF( reg ) = val; } while (0) #define MGA_WRITE8( reg, val ) do { MGA_DEREF8( reg ) = val; } while (0) #endif @@ -345,6 +348,11 @@ do { \ /* A reduced set of the mga registers. */ #define MGA_CRTC_INDEX 0x1fd4 +#define MGA_CRTC_DATA 0x1fd5 + +/* CRTC11 */ +#define MGA_VINTCLR (1 << 4) +#define MGA_VINTEN (1 << 5) #define MGA_ALPHACTRL 0x2c7c #define MGA_AR0 0x1c60 @@ -416,8 +424,10 @@ do { \ #define MGA_ICLEAR 0x1e18 # define MGA_SOFTRAPICLR (1 << 0) +# define MGA_VLINEICLR (1 << 5) #define MGA_IEN 0x1e1c # define MGA_SOFTRAPIEN (1 << 0) +# define MGA_VLINEIEN (1 << 5) #define MGA_LEN 0x1c5c @@ -456,6 +466,8 @@ do { \ # define MGA_SRCACC_AGP (1 << 1) #define MGA_STATUS 0x1e14 # define MGA_SOFTRAPEN (1 << 0) +# define MGA_VSYNCPEN (1 << 4) +# define MGA_VLINEPEN (1 << 5) # define MGA_DWGENGSTS (1 << 16) # define MGA_ENDPRDMASTS (1 << 17) #define MGA_STENCIL 0x2cc8 diff --git a/shared/mga_irq.c b/shared/mga_irq.c new file mode 100644 index 00000000..568d193f --- /dev/null +++ b/shared/mga_irq.c @@ -0,0 +1,99 @@ +/* mga_irq.c -- IRQ handling for radeon -*- linux-c -*- + * + * Copyright (C) The Weather Channel, Inc. 2002. 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 + * PRECISION INSIGHT 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> + */ + +#include "mga.h" +#include "drmP.h" +#include "drm.h" +#include "mga_drm.h" +#include "mga_drv.h" + +void mga_dma_service( DRM_IRQ_ARGS ) +{ + drm_device_t *dev = (drm_device_t *) arg; + drm_mga_private_t *dev_priv = + (drm_mga_private_t *)dev->dev_private; + int status; + + status = MGA_READ( MGA_STATUS ); + + /* VBLANK interrupt */ + if ( status & MGA_VLINEPEN ) { + MGA_WRITE( MGA_ICLEAR, MGA_VLINEICLR ); + atomic_inc(&dev->vbl_received); + DRM_WAKEUP(&dev->vbl_queue); + } +} + +int mga_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 ) <= (1<<23) ) ); + + *sequence = cur_vblank; + + return ret; +} + +void mga_driver_irq_preinstall( drm_device_t *dev ) { + drm_mga_private_t *dev_priv = + (drm_mga_private_t *)dev->dev_private; + + /* Disable *all* interrupts */ + MGA_WRITE( MGA_IEN, 0 ); + /* Clear bits if they're already high */ + MGA_WRITE( MGA_ICLEAR, ~0 ); +} + +void mga_driver_irq_postinstall( drm_device_t *dev ) { + drm_mga_private_t *dev_priv = + (drm_mga_private_t *)dev->dev_private; + + /* Turn on VBL interrupt */ + MGA_WRITE( MGA_IEN, MGA_VLINEIEN ); +} + +void mga_driver_irq_uninstall( drm_device_t *dev ) { + drm_mga_private_t *dev_priv = + (drm_mga_private_t *)dev->dev_private; + if ( dev_priv ) { + /* Disable *all* interrupts */ + MGA_WRITE( MGA_IEN, 0 ); + } +} diff --git a/shared/mga_state.c b/shared/mga_state.c index 5e5b594a..61077220 100644 --- a/shared/mga_state.c +++ b/shared/mga_state.c @@ -26,7 +26,7 @@ * * Authors: * Jeff Hartmann <jhartmann@valinux.com> - * Keith Whitwell <keithw@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> * * Rewritten by: * Gareth Hughes <gareth@valinux.com> @@ -1075,3 +1075,36 @@ int mga_dma_blit( DRM_IOCTL_ARGS ) return 0; } + +int mga_getparam( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_mga_private_t *dev_priv = dev->dev_private; + drm_mga_getparam_t param; + int value; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL( param, (drm_mga_getparam_t *)data, + sizeof(param) ); + + DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID ); + + switch( param.param ) { + case MGA_PARAM_IRQ_NR: + value = dev->irq; + break; + default: + return DRM_ERR(EINVAL); + } + + if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return DRM_ERR(EFAULT); + } + + return 0; +} diff --git a/shared/r128.h b/shared/r128.h index 472a8014..cdf18ffb 100644 --- a/shared/r128.h +++ b/shared/r128.h @@ -47,10 +47,10 @@ #define DRIVER_NAME "r128" #define DRIVER_DESC "ATI Rage 128" -#define DRIVER_DATE "20010917" +#define DRIVER_DATE "20021029" #define DRIVER_MAJOR 2 -#define DRIVER_MINOR 2 +#define DRIVER_MINOR 3 #define DRIVER_PATCHLEVEL 0 @@ -70,7 +70,8 @@ [DRM_IOCTL_NR(DRM_IOCTL_R128_BLIT)] = { r128_cce_blit, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_R128_DEPTH)] = { r128_cce_depth, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_R128_STIPPLE)] = { r128_cce_stipple, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_R128_INDIRECT)] = { r128_cce_indirect, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_INDIRECT)] = { r128_cce_indirect, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_R128_GETPARAM)] = { r128_getparam, 1, 1 }, /* Driver customization: */ @@ -90,6 +91,9 @@ /* DMA customization: */ #define __HAVE_DMA 1 +#define __HAVE_DMA_IRQ 1 +#define __HAVE_VBL_IRQ 1 +#define __HAVE_SHARED_IRQ 1 #if 0 /* GH: Remove this for now... */ diff --git a/shared/r128_drm.h b/shared/r128_drm.h index a8d23008..bbb1a93b 100644 --- a/shared/r128_drm.h +++ b/shared/r128_drm.h @@ -190,6 +190,7 @@ typedef struct drm_r128_sarea { #define DRM_IOCTL_R128_INDIRECT DRM_IOWR(0x4f, drm_r128_indirect_t) #define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( 0x50, drm_r128_fullscreen_t) #define DRM_IOCTL_R128_CLEAR2 DRM_IOW( 0x51, drm_r128_clear2_t) +#define DRM_IOCTL_R128_GETPARAM DRM_IOW( 0x52, drm_r128_getparam_t) typedef struct drm_r128_init { enum { @@ -305,4 +306,14 @@ typedef struct drm_r128_fullscreen { } func; } drm_r128_fullscreen_t; +/* 2.3: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define R128_PARAM_IRQ_NR 1 + +typedef struct drm_r128_getparam { + int param; + int *value; +} drm_r128_getparam_t; + #endif diff --git a/shared/r128_drv.h b/shared/r128_drv.h index aeb73e08..763fcb3a 100644 --- a/shared/r128_drv.h +++ b/shared/r128_drv.h @@ -124,6 +124,7 @@ extern int r128_cce_idle( DRM_IOCTL_ARGS ); extern int r128_engine_reset( DRM_IOCTL_ARGS ); extern int r128_fullscreen( DRM_IOCTL_ARGS ); extern int r128_cce_buffers( DRM_IOCTL_ARGS ); +extern int r128_getparam( DRM_IOCTL_ARGS ); extern void r128_freelist_reset( drm_device_t *dev ); extern drm_buf_t *r128_freelist_get( drm_device_t *dev ); @@ -213,6 +214,11 @@ extern int r128_cce_indirect( DRM_IOCTL_ARGS ); #define R128_DST_PITCH_OFFSET_C 0x1c80 # define R128_DST_TILE (1 << 31) +#define R128_GEN_INT_CNTL 0x0040 +# define R128_CRTC_VBLANK_INT_EN (1 << 0) +#define R128_GEN_INT_STATUS 0x0044 +# define R128_CRTC_VBLANK_INT (1 << 0) +# define R128_CRTC_VBLANK_INT_AK (1 << 0) #define R128_GEN_RESET_CNTL 0x00f0 # define R128_SOFT_RESET_GUI (1 << 0) diff --git a/shared/r128_irq.c b/shared/r128_irq.c new file mode 100644 index 00000000..a29a81b5 --- /dev/null +++ b/shared/r128_irq.c @@ -0,0 +1,99 @@ +/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*- + * + * Copyright (C) The Weather Channel, Inc. 2002. 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 + * PRECISION INSIGHT 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> + */ + +#include "r128.h" +#include "drmP.h" +#include "drm.h" +#include "r128_drm.h" +#include "r128_drv.h" + +void r128_dma_service( DRM_IRQ_ARGS ) +{ + drm_device_t *dev = (drm_device_t *) arg; + drm_r128_private_t *dev_priv = + (drm_r128_private_t *)dev->dev_private; + int status; + + status = R128_READ( R128_GEN_INT_STATUS ); + + /* VBLANK interrupt */ + if ( status & R128_CRTC_VBLANK_INT ) { + R128_WRITE( R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK ); + atomic_inc(&dev->vbl_received); + DRM_WAKEUP(&dev->vbl_queue); + } +} + +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 ) <= (1<<23) ) ); + + *sequence = cur_vblank; + + return ret; +} + +void r128_driver_irq_preinstall( drm_device_t *dev ) { + drm_r128_private_t *dev_priv = + (drm_r128_private_t *)dev->dev_private; + + /* Disable *all* interrupts */ + R128_WRITE( R128_GEN_INT_CNTL, 0 ); + /* Clear vblank bit if it's already high */ + R128_WRITE( R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK ); +} + +void r128_driver_irq_postinstall( drm_device_t *dev ) { + drm_r128_private_t *dev_priv = + (drm_r128_private_t *)dev->dev_private; + + /* Turn on VBL interrupt */ + R128_WRITE( R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN ); +} + +void r128_driver_irq_uninstall( drm_device_t *dev ) { + drm_r128_private_t *dev_priv = + (drm_r128_private_t *)dev->dev_private; + if ( dev_priv ) { + /* Disable *all* interrupts */ + R128_WRITE( R128_GEN_INT_CNTL, 0 ); + } +} diff --git a/shared/r128_state.c b/shared/r128_state.c index 6ae58639..68f73061 100644 --- a/shared/r128_state.c +++ b/shared/r128_state.c @@ -1564,3 +1564,36 @@ int r128_cce_indirect( DRM_IOCTL_ARGS ) return 0; } + +int r128_getparam( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_getparam_t param; + int value; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL( param, (drm_r128_getparam_t *)data, + sizeof(param) ); + + DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID ); + + switch( param.param ) { + case R128_PARAM_IRQ_NR: + value = dev->irq; + break; + default: + return DRM_ERR(EINVAL); + } + + if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return DRM_ERR(EFAULT); + } + + return 0; +} diff --git a/shared/radeon_drm.h b/shared/radeon_drm.h index 91b395c3..f05507e2 100644 --- a/shared/radeon_drm.h +++ b/shared/radeon_drm.h @@ -27,7 +27,7 @@ * Authors: * Kevin E. Martin <martin@valinux.com> * Gareth Hughes <gareth@valinux.com> - * Keith Whitwell <keith_whitwell@yahoo.com> + * Keith Whitwell <keith@tungstengraphics.com> */ #ifndef __RADEON_DRM_H__ @@ -355,6 +355,7 @@ typedef struct { int ctx_owner; int pfState; /* number of 3d windows (0,1,2ormore) */ int pfCurrentPage; /* which buffer is being displayed? */ + int crtc2_base; /* CRTC2 frame offset */ } drm_radeon_sarea_t; diff --git a/shared/radeon_drv.h b/shared/radeon_drv.h index 81615a78..65f3c926 100644 --- a/shared/radeon_drv.h +++ b/shared/radeon_drv.h @@ -109,8 +109,6 @@ typedef struct drm_radeon_private { int do_boxes; int page_flipping; int current_page; - u32 crtc_offset; - u32 crtc_offset_cntl; u32 color_fmt; unsigned int front_offset; @@ -230,6 +228,8 @@ extern int radeon_emit_irq(drm_device_t *dev); #define RADEON_CRTC_OFFSET_CNTL 0x0228 # define RADEON_CRTC_TILE_EN (1 << 15) # define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16) +#define RADEON_CRTC2_OFFSET 0x0324 +#define RADEON_CRTC2_OFFSET_CNTL 0x0328 #define RADEON_RB3D_COLORPITCH 0x1c48 diff --git a/shared/radeon_state.c b/shared/radeon_state.c index b4d66524..7b480a7e 100644 --- a/shared/radeon_state.c +++ b/shared/radeon_state.c @@ -30,6 +30,7 @@ #include "radeon.h" #include "drmP.h" #include "drm.h" +#include "drm_sarea.h" #include "radeon_drm.h" #include "radeon_drv.h" @@ -803,6 +804,9 @@ static void radeon_cp_dispatch_swap( drm_device_t *dev ) static void radeon_cp_dispatch_flip( drm_device_t *dev ) { drm_radeon_private_t *dev_priv = dev->dev_private; + drm_sarea_t *sarea = (drm_sarea_t *)dev_priv->sarea->handle; + int offset = (dev_priv->current_page == 1) + ? dev_priv->front_offset : dev_priv->back_offset; RING_LOCALS; DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n", __FUNCTION__, @@ -816,18 +820,17 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev ) radeon_cp_performance_boxes( dev_priv ); } - BEGIN_RING( 4 ); + /* Update the frame offsets for both CRTCs + */ + BEGIN_RING( 6 ); RADEON_WAIT_UNTIL_3D_IDLE(); - OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET, 0 ) ); - - if ( dev_priv->current_page == 0 ) { - OUT_RING( dev_priv->back_offset ); - dev_priv->current_page = 1; - } else { - OUT_RING( dev_priv->front_offset ); - dev_priv->current_page = 0; - } + OUT_RING_REG( RADEON_CRTC_OFFSET, ( ( sarea->frame.y * dev_priv->front_pitch + + sarea->frame.x + * ( dev_priv->color_fmt - 2 ) ) & ~7 ) + + offset ); + OUT_RING_REG( RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base + + offset ); ADVANCE_RING(); @@ -836,7 +839,8 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev ) * performing the swapbuffer ioctl. */ dev_priv->sarea_priv->last_frame++; - dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page; + dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page = + 1 - dev_priv->current_page; BEGIN_RING( 2 ); @@ -1304,12 +1308,12 @@ static int radeon_do_init_pageflip( drm_device_t *dev ) DRM_DEBUG( "\n" ); - dev_priv->crtc_offset_cntl = RADEON_READ( RADEON_CRTC_OFFSET_CNTL ); - - BEGIN_RING( 4 ); + BEGIN_RING( 6 ); RADEON_WAIT_UNTIL_3D_IDLE(); OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET_CNTL, 0 ) ); - OUT_RING( dev_priv->crtc_offset_cntl | RADEON_CRTC_OFFSET_FLIP_CNTL ); + OUT_RING( RADEON_READ( RADEON_CRTC_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL ); + OUT_RING( CP_PACKET0( RADEON_CRTC2_OFFSET_CNTL, 0 ) ); + OUT_RING( RADEON_READ( RADEON_CRTC2_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL ); ADVANCE_RING(); dev_priv->page_flipping = 1; @@ -1330,10 +1334,6 @@ int radeon_do_cleanup_pageflip( drm_device_t *dev ) if (dev_priv->current_page != 0) radeon_cp_dispatch_flip( dev ); - /* FIXME: If the X server changes screen resolution, it - * clobbers the value of RADEON_CRTC_OFFSET_CNTL, above, - * leading to a flashing efect. - */ dev_priv->page_flipping = 0; return 0; } |