Merged ati-pcigart-1-0-0
parent
a15b9dec3c
commit
5d6ddbca26
|
@ -67,11 +67,6 @@ extern int xf86RemoveSIGIOHandler(int fd);
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __alpha__
|
|
||||||
extern unsigned long _bus_base(void);
|
|
||||||
#define BUS_BASE _bus_base()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Not all systems have MAP_FAILED defined */
|
/* Not all systems have MAP_FAILED defined */
|
||||||
#ifndef MAP_FAILED
|
#ifndef MAP_FAILED
|
||||||
#define MAP_FAILED ((void *)-1)
|
#define MAP_FAILED ((void *)-1)
|
||||||
|
@ -490,11 +485,6 @@ int drmAddMap(int fd,
|
||||||
drm_map_t map;
|
drm_map_t map;
|
||||||
|
|
||||||
map.offset = offset;
|
map.offset = offset;
|
||||||
#ifdef __alpha__
|
|
||||||
/* Make sure we add the bus_base to all but shm */
|
|
||||||
if (type != DRM_SHM)
|
|
||||||
map.offset += BUS_BASE;
|
|
||||||
#endif
|
|
||||||
map.size = size;
|
map.size = size;
|
||||||
map.handle = 0;
|
map.handle = 0;
|
||||||
map.type = type;
|
map.type = type;
|
||||||
|
@ -998,6 +988,28 @@ unsigned int drmAgpDeviceId(int fd)
|
||||||
return i.id_device;
|
return i.id_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int drmScatterGatherAlloc(int fd, unsigned long size, unsigned long *handle)
|
||||||
|
{
|
||||||
|
drm_scatter_gather_t sg;
|
||||||
|
|
||||||
|
*handle = 0;
|
||||||
|
sg.size = size;
|
||||||
|
sg.handle = 0;
|
||||||
|
if (ioctl(fd, DRM_IOCTL_SG_ALLOC, &sg)) return -errno;
|
||||||
|
*handle = sg.handle;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int drmScatterGatherFree(int fd, unsigned long handle)
|
||||||
|
{
|
||||||
|
drm_scatter_gather_t sg;
|
||||||
|
|
||||||
|
sg.size = 0;
|
||||||
|
sg.handle = handle;
|
||||||
|
if (ioctl(fd, DRM_IOCTL_SG_FREE, &sg)) return -errno;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int drmError(int err, const char *label)
|
int drmError(int err, const char *label)
|
||||||
{
|
{
|
||||||
switch (err) {
|
switch (err) {
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
/* ati_pcigart.h -- ATI PCI GART support -*- linux-c -*-
|
||||||
|
* Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com
|
||||||
|
*
|
||||||
|
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||||
|
* 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
|
||||||
|
* 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:
|
||||||
|
* Gareth Hughes <gareth@valinux.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define __NO_VERSION__
|
||||||
|
#include "drmP.h"
|
||||||
|
|
||||||
|
#if PAGE_SIZE == 8192
|
||||||
|
# define ATI_PCIGART_TABLE_ORDER 2
|
||||||
|
# define ATI_PCIGART_TABLE_PAGES (1 << 2)
|
||||||
|
#elif PAGE_SIZE == 4096
|
||||||
|
# define ATI_PCIGART_TABLE_ORDER 3
|
||||||
|
# define ATI_PCIGART_TABLE_PAGES (1 << 3)
|
||||||
|
#elif
|
||||||
|
# error - PAGE_SIZE not 8K or 4K
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# define ATI_MAX_PCIGART_PAGES 8192 /* 32 MB aperture, 4K pages */
|
||||||
|
# define ATI_PCIGART_PAGE_SIZE 4096 /* PCI GART page size */
|
||||||
|
|
||||||
|
static unsigned long DRM(ati_alloc_pcigart_table)( void )
|
||||||
|
{
|
||||||
|
unsigned long address;
|
||||||
|
struct page *page;
|
||||||
|
int i;
|
||||||
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
|
address = __get_free_pages( GFP_KERNEL, ATI_PCIGART_TABLE_ORDER );
|
||||||
|
if ( address == 0UL ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
page = virt_to_page( address );
|
||||||
|
|
||||||
|
for ( i = 0 ; i <= ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
|
||||||
|
atomic_inc( &page->count );
|
||||||
|
SetPageReserved( page );
|
||||||
|
}
|
||||||
|
|
||||||
|
DRM_DEBUG( "%s: returning 0x%08lx\n", __FUNCTION__, address );
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DRM(ati_free_pcigart_table)( unsigned long address )
|
||||||
|
{
|
||||||
|
struct page *page;
|
||||||
|
int i;
|
||||||
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
|
if ( !address ) return;
|
||||||
|
|
||||||
|
page = virt_to_page( address );
|
||||||
|
|
||||||
|
for ( i = 0 ; i <= ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
|
||||||
|
atomic_dec( &page->count );
|
||||||
|
ClearPageReserved( page );
|
||||||
|
}
|
||||||
|
|
||||||
|
free_pages( address, ATI_PCIGART_TABLE_ORDER );
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long DRM(ati_pcigart_init)( drm_device_t *dev )
|
||||||
|
{
|
||||||
|
drm_sg_mem_t *entry = dev->sg;
|
||||||
|
unsigned long address;
|
||||||
|
unsigned long pages;
|
||||||
|
u32 *pci_gart, page_base;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if ( !entry ) {
|
||||||
|
DRM_ERROR( "no scatter/gather memory!\n" );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
address = DRM(ati_alloc_pcigart_table)();
|
||||||
|
if ( !address ) {
|
||||||
|
DRM_ERROR( "cannot allocate PCI GART page!\n" );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pci_gart = (u32 *)address;
|
||||||
|
|
||||||
|
pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
|
||||||
|
? entry->pages : ATI_MAX_PCIGART_PAGES;
|
||||||
|
|
||||||
|
memset( pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32) );
|
||||||
|
|
||||||
|
for ( i = 0 ; i < pages ; i++ ) {
|
||||||
|
page_base = virt_to_bus( entry->pagelist[i]->virtual );
|
||||||
|
for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
|
||||||
|
*pci_gart++ = cpu_to_le32( page_base );
|
||||||
|
page_base += ATI_PCIGART_PAGE_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __i386__
|
||||||
|
asm volatile ( "wbinvd" ::: "memory" );
|
||||||
|
#else
|
||||||
|
mb();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DRM(ati_pcigart_cleanup)( unsigned long address )
|
||||||
|
{
|
||||||
|
|
||||||
|
if ( address ) {
|
||||||
|
DRM(ati_free_pcigart_table)( address );
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -53,7 +53,7 @@
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/smp_lock.h> /* For (un)lock_kernel */
|
#include <linux/smp_lock.h> /* For (un)lock_kernel */
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#ifdef __alpha__
|
#if defined(__alpha__) || defined(__powerpc__)
|
||||||
#include <asm/pgtable.h> /* For pte_wrprotect */
|
#include <asm/pgtable.h> /* For pte_wrprotect */
|
||||||
#endif
|
#endif
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
@ -145,6 +145,7 @@
|
||||||
#define DRM_MEM_BOUNDAGP 17
|
#define DRM_MEM_BOUNDAGP 17
|
||||||
#define DRM_MEM_CTXBITMAP 18
|
#define DRM_MEM_CTXBITMAP 18
|
||||||
#define DRM_MEM_STUB 19
|
#define DRM_MEM_STUB 19
|
||||||
|
#define DRM_MEM_SGLISTS 20
|
||||||
|
|
||||||
#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
|
#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
|
||||||
|
|
||||||
|
@ -199,7 +200,7 @@ __cmpxchg_u32(volatile int *m, int old, int new)
|
||||||
unsigned long prev, cmp;
|
unsigned long prev, cmp;
|
||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
"1: ldl_l %0,%2\n"
|
"1: ldl_l %0,%5\n"
|
||||||
" cmpeq %0,%3,%1\n"
|
" cmpeq %0,%3,%1\n"
|
||||||
" beq %1,2f\n"
|
" beq %1,2f\n"
|
||||||
" mov %4,%1\n"
|
" mov %4,%1\n"
|
||||||
|
@ -210,7 +211,8 @@ __cmpxchg_u32(volatile int *m, int old, int new)
|
||||||
"3: br 1b\n"
|
"3: br 1b\n"
|
||||||
".previous"
|
".previous"
|
||||||
: "=&r"(prev), "=&r"(cmp), "=m"(*m)
|
: "=&r"(prev), "=&r"(cmp), "=m"(*m)
|
||||||
: "r"((long) old), "r"(new), "m"(*m));
|
: "r"((long) old), "r"(new), "m"(*m)
|
||||||
|
: "memory" );
|
||||||
|
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
@ -221,7 +223,7 @@ __cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
|
||||||
unsigned long prev, cmp;
|
unsigned long prev, cmp;
|
||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
"1: ldq_l %0,%2\n"
|
"1: ldq_l %0,%5\n"
|
||||||
" cmpeq %0,%3,%1\n"
|
" cmpeq %0,%3,%1\n"
|
||||||
" beq %1,2f\n"
|
" beq %1,2f\n"
|
||||||
" mov %4,%1\n"
|
" mov %4,%1\n"
|
||||||
|
@ -232,7 +234,8 @@ __cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
|
||||||
"3: br 1b\n"
|
"3: br 1b\n"
|
||||||
".previous"
|
".previous"
|
||||||
: "=&r"(prev), "=&r"(cmp), "=m"(*m)
|
: "=&r"(prev), "=&r"(cmp), "=m"(*m)
|
||||||
: "r"((long) old), "r"(new), "m"(*m));
|
: "r"((long) old), "r"(new), "m"(*m)
|
||||||
|
: "memory" );
|
||||||
|
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
@ -284,12 +287,43 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(__powerpc__)
|
||||||
|
extern void __cmpxchg_called_with_bad_pointer(void);
|
||||||
|
static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
|
||||||
|
unsigned long new, int size)
|
||||||
|
{
|
||||||
|
unsigned long prev;
|
||||||
|
|
||||||
|
switch (size) {
|
||||||
|
case 4:
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"sync;"
|
||||||
|
"0: lwarx %0,0,%1 ;"
|
||||||
|
" cmpl 0,%0,%3;"
|
||||||
|
" bne 1f;"
|
||||||
|
" stwcx. %2,0,%1;"
|
||||||
|
" bne- 0b;"
|
||||||
|
"1: "
|
||||||
|
"sync;"
|
||||||
|
: "=&r"(prev)
|
||||||
|
: "r"(ptr), "r"(new), "r"(old)
|
||||||
|
: "cr0", "memory");
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
__cmpxchg_called_with_bad_pointer();
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* i386, powerpc & alpha */
|
||||||
|
|
||||||
|
#ifndef __alpha__
|
||||||
#define cmpxchg(ptr,o,n) \
|
#define cmpxchg(ptr,o,n) \
|
||||||
((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o), \
|
((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o), \
|
||||||
(unsigned long)(n),sizeof(*(ptr))))
|
(unsigned long)(n),sizeof(*(ptr))))
|
||||||
#endif /* i386 & alpha */
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* !__HAVE_ARCH_CMPXCHG */
|
||||||
|
|
||||||
/* Macros to make printk easier */
|
/* Macros to make printk easier */
|
||||||
#define DRM_ERROR(fmt, arg...) \
|
#define DRM_ERROR(fmt, arg...) \
|
||||||
printk(KERN_ERR "[" DRM_NAME ":" __FUNCTION__ "] *ERROR* " fmt , ##arg)
|
printk(KERN_ERR "[" DRM_NAME ":" __FUNCTION__ "] *ERROR* " fmt , ##arg)
|
||||||
|
@ -547,7 +581,8 @@ typedef struct drm_device_dma {
|
||||||
unsigned long *pagelist;
|
unsigned long *pagelist;
|
||||||
unsigned long byte_count;
|
unsigned long byte_count;
|
||||||
enum {
|
enum {
|
||||||
_DRM_DMA_USE_AGP = 0x01
|
_DRM_DMA_USE_AGP = 0x01,
|
||||||
|
_DRM_DMA_USE_SG = 0x02
|
||||||
} flags;
|
} flags;
|
||||||
|
|
||||||
/* DMA support */
|
/* DMA support */
|
||||||
|
@ -579,6 +614,13 @@ typedef struct drm_agp_head {
|
||||||
} drm_agp_head_t;
|
} drm_agp_head_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef struct drm_sg_mem {
|
||||||
|
unsigned long handle;
|
||||||
|
void *virtual;
|
||||||
|
int pages;
|
||||||
|
struct page **pagelist;
|
||||||
|
} drm_sg_mem_t;
|
||||||
|
|
||||||
typedef struct drm_sigdata {
|
typedef struct drm_sigdata {
|
||||||
int context;
|
int context;
|
||||||
drm_hw_lock_t *lock;
|
drm_hw_lock_t *lock;
|
||||||
|
@ -667,6 +709,10 @@ typedef struct drm_device {
|
||||||
#if __REALLY_HAVE_AGP
|
#if __REALLY_HAVE_AGP
|
||||||
drm_agp_head_t *agp;
|
drm_agp_head_t *agp;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef __alpha__
|
||||||
|
struct pci_controler *hose;
|
||||||
|
#endif
|
||||||
|
drm_sg_mem_t *sg; /* Scatter gather memory */
|
||||||
unsigned long *ctx_bitmap;
|
unsigned long *ctx_bitmap;
|
||||||
void *dev_private;
|
void *dev_private;
|
||||||
drm_sigdata_t sigdata; /* For block_all_signals */
|
drm_sigdata_t sigdata; /* For block_all_signals */
|
||||||
|
@ -718,6 +764,9 @@ extern unsigned long DRM(vm_shm_nopage)(struct vm_area_struct *vma,
|
||||||
extern unsigned long DRM(vm_dma_nopage)(struct vm_area_struct *vma,
|
extern unsigned long DRM(vm_dma_nopage)(struct vm_area_struct *vma,
|
||||||
unsigned long address,
|
unsigned long address,
|
||||||
int write_access);
|
int write_access);
|
||||||
|
extern unsigned long DRM(vm_sg_nopage)(struct vm_area_struct *vma,
|
||||||
|
unsigned long address,
|
||||||
|
int write_access);
|
||||||
#else
|
#else
|
||||||
/* Return type changed in 2.3.23 */
|
/* Return type changed in 2.3.23 */
|
||||||
extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
|
extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
|
||||||
|
@ -729,6 +778,9 @@ extern struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
|
||||||
extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
|
extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
|
||||||
unsigned long address,
|
unsigned long address,
|
||||||
int write_access);
|
int write_access);
|
||||||
|
extern struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
|
||||||
|
unsigned long address,
|
||||||
|
int write_access);
|
||||||
#endif
|
#endif
|
||||||
extern void DRM(vm_open)(struct vm_area_struct *vma);
|
extern void DRM(vm_open)(struct vm_area_struct *vma);
|
||||||
extern void DRM(vm_close)(struct vm_area_struct *vma);
|
extern void DRM(vm_close)(struct vm_area_struct *vma);
|
||||||
|
@ -947,5 +999,16 @@ extern int DRM(proc_cleanup)(int minor,
|
||||||
struct proc_dir_entry *root,
|
struct proc_dir_entry *root,
|
||||||
struct proc_dir_entry *dev_root);
|
struct proc_dir_entry *dev_root);
|
||||||
|
|
||||||
|
/* Scatter Gather Support (drm_scatter.h) */
|
||||||
|
extern void DRM(sg_cleanup)(drm_sg_mem_t *entry);
|
||||||
|
extern int DRM(sg_alloc)(struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
extern int DRM(sg_free)(struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
|
||||||
|
/* ATI PCIGART support (ati_pcigart.h) */
|
||||||
|
extern unsigned long DRM(ati_pcigart_init)(drm_device_t *dev);
|
||||||
|
extern int DRM(ati_pcigart_cleanup)(unsigned long address);
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -52,7 +52,8 @@ int DRM(agp_info)(struct inode *inode, struct file *filp,
|
||||||
agp_kern_info *kern;
|
agp_kern_info *kern;
|
||||||
drm_agp_info_t info;
|
drm_agp_info_t info;
|
||||||
|
|
||||||
if (!dev->agp->acquired || !drm_agp->copy_info) return -EINVAL;
|
if (!dev->agp || !dev->agp->acquired || !drm_agp->copy_info)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
kern = &dev->agp->agp_info;
|
kern = &dev->agp->agp_info;
|
||||||
info.agp_version_major = kern->version.major;
|
info.agp_version_major = kern->version.major;
|
||||||
|
@ -77,7 +78,8 @@ int DRM(agp_acquire)(struct inode *inode, struct file *filp,
|
||||||
drm_device_t *dev = priv->dev;
|
drm_device_t *dev = priv->dev;
|
||||||
int retcode;
|
int retcode;
|
||||||
|
|
||||||
if (!dev->agp|| dev->agp->acquired || !drm_agp->acquire) return -EINVAL;
|
if (!dev->agp || dev->agp->acquired || !drm_agp->acquire)
|
||||||
|
return -EINVAL;
|
||||||
if ((retcode = drm_agp->acquire())) return retcode;
|
if ((retcode = drm_agp->acquire())) return retcode;
|
||||||
dev->agp->acquired = 1;
|
dev->agp->acquired = 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -89,7 +91,8 @@ int DRM(agp_release)(struct inode *inode, struct file *filp,
|
||||||
drm_file_t *priv = filp->private_data;
|
drm_file_t *priv = filp->private_data;
|
||||||
drm_device_t *dev = priv->dev;
|
drm_device_t *dev = priv->dev;
|
||||||
|
|
||||||
if (!dev->agp->acquired || !drm_agp->release) return -EINVAL;
|
if (!dev->agp || !dev->agp->acquired || !drm_agp->release)
|
||||||
|
return -EINVAL;
|
||||||
drm_agp->release();
|
drm_agp->release();
|
||||||
dev->agp->acquired = 0;
|
dev->agp->acquired = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -108,7 +111,8 @@ int DRM(agp_enable)(struct inode *inode, struct file *filp,
|
||||||
drm_device_t *dev = priv->dev;
|
drm_device_t *dev = priv->dev;
|
||||||
drm_agp_mode_t mode;
|
drm_agp_mode_t mode;
|
||||||
|
|
||||||
if (!dev->agp->acquired || !drm_agp->enable) return -EINVAL;
|
if (!dev->agp || !dev->agp->acquired || !drm_agp->enable)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
if (copy_from_user(&mode, (drm_agp_mode_t *)arg, sizeof(mode)))
|
if (copy_from_user(&mode, (drm_agp_mode_t *)arg, sizeof(mode)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
@ -131,7 +135,7 @@ int DRM(agp_alloc)(struct inode *inode, struct file *filp,
|
||||||
unsigned long pages;
|
unsigned long pages;
|
||||||
u32 type;
|
u32 type;
|
||||||
|
|
||||||
if (!dev->agp->acquired) return -EINVAL;
|
if (!dev->agp || !dev->agp->acquired) return -EINVAL;
|
||||||
if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
|
if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (!(entry = DRM(alloc)(sizeof(*entry), DRM_MEM_AGPLISTS)))
|
if (!(entry = DRM(alloc)(sizeof(*entry), DRM_MEM_AGPLISTS)))
|
||||||
|
@ -188,7 +192,7 @@ int DRM(agp_unbind)(struct inode *inode, struct file *filp,
|
||||||
drm_agp_binding_t request;
|
drm_agp_binding_t request;
|
||||||
drm_agp_mem_t *entry;
|
drm_agp_mem_t *entry;
|
||||||
|
|
||||||
if (!dev->agp->acquired) return -EINVAL;
|
if (!dev->agp || !dev->agp->acquired) return -EINVAL;
|
||||||
if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
|
if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
|
if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
|
||||||
|
@ -207,7 +211,8 @@ int DRM(agp_bind)(struct inode *inode, struct file *filp,
|
||||||
int retcode;
|
int retcode;
|
||||||
int page;
|
int page;
|
||||||
|
|
||||||
if (!dev->agp->acquired || !drm_agp->bind_memory) return -EINVAL;
|
if (!dev->agp || !dev->agp->acquired || !drm_agp->bind_memory)
|
||||||
|
return -EINVAL;
|
||||||
if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
|
if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
|
if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
|
||||||
|
@ -229,7 +234,7 @@ int DRM(agp_free)(struct inode *inode, struct file *filp,
|
||||||
drm_agp_buffer_t request;
|
drm_agp_buffer_t request;
|
||||||
drm_agp_mem_t *entry;
|
drm_agp_mem_t *entry;
|
||||||
|
|
||||||
if (!dev->agp->acquired) return -EINVAL;
|
if (!dev->agp || !dev->agp->acquired) return -EINVAL;
|
||||||
if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
|
if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
|
if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
|
||||||
|
|
|
@ -37,6 +37,10 @@
|
||||||
#define __HAVE_PCI_DMA 0
|
#define __HAVE_PCI_DMA 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __HAVE_SG
|
||||||
|
#define __HAVE_SG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef DRIVER_BUF_PRIV_T
|
#ifndef DRIVER_BUF_PRIV_T
|
||||||
#define DRIVER_BUF_PRIV_T u32
|
#define DRIVER_BUF_PRIV_T u32
|
||||||
#endif
|
#endif
|
||||||
|
@ -103,13 +107,16 @@ int DRM(addmap)( struct inode *inode, struct file *filp,
|
||||||
switch ( map->type ) {
|
switch ( map->type ) {
|
||||||
case _DRM_REGISTERS:
|
case _DRM_REGISTERS:
|
||||||
case _DRM_FRAME_BUFFER:
|
case _DRM_FRAME_BUFFER:
|
||||||
#ifndef __sparc__
|
#if !defined(__sparc__) && !defined(__alpha__)
|
||||||
if ( map->offset + map->size < map->offset ||
|
if ( map->offset + map->size < map->offset ||
|
||||||
map->offset < virt_to_phys(high_memory) ) {
|
map->offset < virt_to_phys(high_memory) ) {
|
||||||
DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
|
DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef __alpha__
|
||||||
|
map->offset += dev->hose->mem_space->start;
|
||||||
|
#endif
|
||||||
#if __REALLY_HAVE_MTRR
|
#if __REALLY_HAVE_MTRR
|
||||||
if ( map->type == _DRM_FRAME_BUFFER ||
|
if ( map->type == _DRM_FRAME_BUFFER ||
|
||||||
(map->flags & _DRM_WRITE_COMBINING) ) {
|
(map->flags & _DRM_WRITE_COMBINING) ) {
|
||||||
|
@ -135,10 +142,21 @@ int DRM(addmap)( struct inode *inode, struct file *filp,
|
||||||
break;
|
break;
|
||||||
#if __REALLY_HAVE_AGP
|
#if __REALLY_HAVE_AGP
|
||||||
case _DRM_AGP:
|
case _DRM_AGP:
|
||||||
|
#ifdef __alpha__
|
||||||
|
map->offset += dev->hose->mem_space->start;
|
||||||
|
#endif
|
||||||
map->offset = map->offset + dev->agp->base;
|
map->offset = map->offset + dev->agp->base;
|
||||||
map->mtrr = dev->agp->agp_mtrr; /* for getmap */
|
map->mtrr = dev->agp->agp_mtrr; /* for getmap */
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
case _DRM_SCATTER_GATHER:
|
||||||
|
if (!dev->sg) {
|
||||||
|
DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
map->offset = map->offset + dev->sg->handle;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
|
DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -237,6 +255,7 @@ int DRM(rmmap)(struct inode *inode, struct file *filp,
|
||||||
vfree(map->handle);
|
vfree(map->handle);
|
||||||
break;
|
break;
|
||||||
case _DRM_AGP:
|
case _DRM_AGP:
|
||||||
|
case _DRM_SCATTER_GATHER:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
|
DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
|
||||||
|
@ -565,6 +584,159 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp,
|
||||||
}
|
}
|
||||||
#endif /* __HAVE_PCI_DMA */
|
#endif /* __HAVE_PCI_DMA */
|
||||||
|
|
||||||
|
#ifdef __HAVE_SG
|
||||||
|
int DRM(addbufs_sg)( struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg )
|
||||||
|
{
|
||||||
|
drm_file_t *priv = filp->private_data;
|
||||||
|
drm_device_t *dev = priv->dev;
|
||||||
|
drm_device_dma_t *dma = dev->dma;
|
||||||
|
drm_buf_desc_t request;
|
||||||
|
drm_buf_entry_t *entry;
|
||||||
|
drm_buf_t *buf;
|
||||||
|
unsigned long offset;
|
||||||
|
unsigned long agp_offset;
|
||||||
|
int count;
|
||||||
|
int order;
|
||||||
|
int size;
|
||||||
|
int alignment;
|
||||||
|
int page_order;
|
||||||
|
int total;
|
||||||
|
int byte_count;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ( !dma ) return -EINVAL;
|
||||||
|
|
||||||
|
if ( copy_from_user( &request, (drm_buf_desc_t *)arg,
|
||||||
|
sizeof(request) ) )
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
count = request.count;
|
||||||
|
order = DRM(order)( request.size );
|
||||||
|
size = 1 << order;
|
||||||
|
|
||||||
|
alignment = (request.flags & _DRM_PAGE_ALIGN)
|
||||||
|
? PAGE_ALIGN(size) : size;
|
||||||
|
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
|
||||||
|
total = PAGE_SIZE << page_order;
|
||||||
|
|
||||||
|
byte_count = 0;
|
||||||
|
agp_offset = request.agp_start;
|
||||||
|
|
||||||
|
DRM_DEBUG( "count: %d\n", count );
|
||||||
|
DRM_DEBUG( "order: %d\n", order );
|
||||||
|
DRM_DEBUG( "size: %d\n", size );
|
||||||
|
DRM_DEBUG( "agp_offset: %ld\n", agp_offset );
|
||||||
|
DRM_DEBUG( "alignment: %d\n", alignment );
|
||||||
|
DRM_DEBUG( "page_order: %d\n", page_order );
|
||||||
|
DRM_DEBUG( "total: %d\n", total );
|
||||||
|
|
||||||
|
if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
|
||||||
|
if ( dev->queue_count ) return -EBUSY; /* Not while in use */
|
||||||
|
|
||||||
|
spin_lock( &dev->count_lock );
|
||||||
|
if ( dev->buf_use ) {
|
||||||
|
spin_unlock( &dev->count_lock );
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
atomic_inc( &dev->buf_alloc );
|
||||||
|
spin_unlock( &dev->count_lock );
|
||||||
|
|
||||||
|
down( &dev->struct_sem );
|
||||||
|
entry = &dma->bufs[order];
|
||||||
|
if ( entry->buf_count ) {
|
||||||
|
up( &dev->struct_sem );
|
||||||
|
atomic_dec( &dev->buf_alloc );
|
||||||
|
return -ENOMEM; /* May only call once for each order */
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist),
|
||||||
|
DRM_MEM_BUFS );
|
||||||
|
if ( !entry->buflist ) {
|
||||||
|
up( &dev->struct_sem );
|
||||||
|
atomic_dec( &dev->buf_alloc );
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
|
||||||
|
|
||||||
|
entry->buf_size = size;
|
||||||
|
entry->page_order = page_order;
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
|
while ( entry->buf_count < count ) {
|
||||||
|
buf = &entry->buflist[entry->buf_count];
|
||||||
|
buf->idx = dma->buf_count + entry->buf_count;
|
||||||
|
buf->total = alignment;
|
||||||
|
buf->order = order;
|
||||||
|
buf->used = 0;
|
||||||
|
|
||||||
|
buf->offset = (dma->byte_count + offset);
|
||||||
|
buf->bus_address = agp_offset + offset;
|
||||||
|
buf->address = (void *)(agp_offset + offset + dev->sg->handle);
|
||||||
|
buf->next = NULL;
|
||||||
|
buf->waiting = 0;
|
||||||
|
buf->pending = 0;
|
||||||
|
init_waitqueue_head( &buf->dma_wait );
|
||||||
|
buf->pid = 0;
|
||||||
|
|
||||||
|
buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T);
|
||||||
|
buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T),
|
||||||
|
DRM_MEM_BUFS );
|
||||||
|
memset( buf->dev_private, 0, buf->dev_priv_size );
|
||||||
|
|
||||||
|
#if __HAVE_DMA_HISTOGRAM
|
||||||
|
buf->time_queued = 0;
|
||||||
|
buf->time_dispatched = 0;
|
||||||
|
buf->time_completed = 0;
|
||||||
|
buf->time_freed = 0;
|
||||||
|
#endif
|
||||||
|
DRM_DEBUG( "buffer %d @ %p\n",
|
||||||
|
entry->buf_count, buf->address );
|
||||||
|
|
||||||
|
offset += alignment;
|
||||||
|
entry->buf_count++;
|
||||||
|
byte_count += PAGE_SIZE << page_order;
|
||||||
|
}
|
||||||
|
|
||||||
|
DRM_DEBUG( "byte_count: %d\n", byte_count );
|
||||||
|
|
||||||
|
dma->buflist = DRM(realloc)( dma->buflist,
|
||||||
|
dma->buf_count * sizeof(*dma->buflist),
|
||||||
|
(dma->buf_count + entry->buf_count)
|
||||||
|
* sizeof(*dma->buflist),
|
||||||
|
DRM_MEM_BUFS );
|
||||||
|
for ( i = 0 ; i < entry->buf_count ; i++ ) {
|
||||||
|
dma->buflist[i + dma->buf_count] = &entry->buflist[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
dma->buf_count += entry->buf_count;
|
||||||
|
dma->byte_count += byte_count;
|
||||||
|
|
||||||
|
DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
|
||||||
|
DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
|
||||||
|
|
||||||
|
#if __HAVE_DMA_FREELIST
|
||||||
|
DRM(freelist_create)( &entry->freelist, entry->buf_count );
|
||||||
|
for ( i = 0 ; i < entry->buf_count ; i++ ) {
|
||||||
|
DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
up( &dev->struct_sem );
|
||||||
|
|
||||||
|
request.count = entry->buf_count;
|
||||||
|
request.size = size;
|
||||||
|
|
||||||
|
if ( copy_to_user( (drm_buf_desc_t *)arg, &request, sizeof(request) ) )
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
dma->flags = _DRM_DMA_USE_SG;
|
||||||
|
|
||||||
|
atomic_dec( &dev->buf_alloc );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* __HAVE_SG */
|
||||||
|
|
||||||
int DRM(addbufs)( struct inode *inode, struct file *filp,
|
int DRM(addbufs)( struct inode *inode, struct file *filp,
|
||||||
unsigned int cmd, unsigned long arg )
|
unsigned int cmd, unsigned long arg )
|
||||||
{
|
{
|
||||||
|
@ -579,6 +751,11 @@ int DRM(addbufs)( struct inode *inode, struct file *filp,
|
||||||
return DRM(addbufs_agp)( inode, filp, cmd, arg );
|
return DRM(addbufs_agp)( inode, filp, cmd, arg );
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
#if __HAVE_SG
|
||||||
|
if ( request.flags & _DRM_SG_BUFFER )
|
||||||
|
return DRM(addbufs_sg)( inode, filp, cmd, arg );
|
||||||
|
else
|
||||||
|
#endif
|
||||||
#if __HAVE_PCI_DMA
|
#if __HAVE_PCI_DMA
|
||||||
return DRM(addbufs_pci)( inode, filp, cmd, arg );
|
return DRM(addbufs_pci)( inode, filp, cmd, arg );
|
||||||
#else
|
#else
|
||||||
|
@ -760,7 +937,8 @@ int DRM(mapbufs)( struct inode *inode, struct file *filp,
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
if ( request.count >= dma->buf_count ) {
|
if ( request.count >= dma->buf_count ) {
|
||||||
if ( __HAVE_AGP && (dma->flags & _DRM_DMA_USE_AGP) ) {
|
if ( (__HAVE_AGP && (dma->flags & _DRM_DMA_USE_AGP)) ||
|
||||||
|
(__HAVE_SG && (dma->flags & _DRM_DMA_USE_SG)) ) {
|
||||||
drm_map_t *map = DRIVER_AGP_BUFFERS_MAP( dev );
|
drm_map_t *map = DRIVER_AGP_BUFFERS_MAP( dev );
|
||||||
|
|
||||||
if ( !map ) {
|
if ( !map ) {
|
||||||
|
|
|
@ -81,6 +81,9 @@
|
||||||
#ifndef __HAVE_COUNTERS
|
#ifndef __HAVE_COUNTERS
|
||||||
#define __HAVE_COUNTERS 0
|
#define __HAVE_COUNTERS 0
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef __HAVE_SG
|
||||||
|
#define __HAVE_SG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef DRIVER_PREINIT
|
#ifndef DRIVER_PREINIT
|
||||||
#define DRIVER_PREINIT()
|
#define DRIVER_PREINIT()
|
||||||
|
@ -178,6 +181,11 @@ static drm_ioctl_desc_t DRM(ioctls)[] = {
|
||||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { DRM(agp_unbind), 1, 1 },
|
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { DRM(agp_unbind), 1, 1 },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if __HAVE_SG
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { DRM(sg_alloc), 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { DRM(sg_free), 1, 1 },
|
||||||
|
#endif
|
||||||
|
|
||||||
DRIVER_IOCTLS
|
DRIVER_IOCTLS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -415,6 +423,12 @@ static int DRM(takedown)( drm_device_t *dev )
|
||||||
* handled in the AGP/GART driver.
|
* handled in the AGP/GART driver.
|
||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
|
case _DRM_SCATTER_GATHER:
|
||||||
|
if(dev->sg) {
|
||||||
|
DRM(sg_cleanup)(dev->sg);
|
||||||
|
dev->sg = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
|
DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,21 @@ int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
|
||||||
}
|
}
|
||||||
up(&dev->struct_sem);
|
up(&dev->struct_sem);
|
||||||
|
|
||||||
|
#ifdef __alpha__
|
||||||
|
/*
|
||||||
|
* Default the hose
|
||||||
|
*/
|
||||||
|
if (!dev->hose) {
|
||||||
|
struct pci_dev *pci_dev;
|
||||||
|
pci_dev = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
|
||||||
|
if (pci_dev) dev->hose = pci_dev->sysdata;
|
||||||
|
if (!dev->hose) {
|
||||||
|
struct pci_bus *b = pci_bus_b(pci_root_buses.next);
|
||||||
|
if (b) dev->hose = b->sysdata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,11 @@
|
||||||
#define __NO_VERSION__
|
#define __NO_VERSION__
|
||||||
#include "drmP.h"
|
#include "drmP.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
int DRM(flags) = DRM_FLAG_DEBUG;
|
||||||
|
#else
|
||||||
int DRM(flags) = 0;
|
int DRM(flags) = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* drm_parse_option parses a single option. See description for
|
/* drm_parse_option parses a single option. See description for
|
||||||
* drm_parse_options for details.
|
* drm_parse_options for details.
|
||||||
|
|
|
@ -95,6 +95,27 @@ int DRM(setunique)(struct inode *inode, struct file *filp,
|
||||||
DRM_MEM_DRIVER);
|
DRM_MEM_DRIVER);
|
||||||
sprintf(dev->devname, "%s@%s", dev->name, dev->unique);
|
sprintf(dev->devname, "%s@%s", dev->name, dev->unique);
|
||||||
|
|
||||||
|
#ifdef __alpha__
|
||||||
|
do {
|
||||||
|
struct pci_dev *pci_dev;
|
||||||
|
int b, d, f;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
for(p = dev->unique; p && *p && *p != ':'; p++);
|
||||||
|
if (!p || !*p) break;
|
||||||
|
b = (int)simple_strtoul(p+1, &p, 10);
|
||||||
|
if (*p != ':') break;
|
||||||
|
d = (int)simple_strtoul(p+1, &p, 10);
|
||||||
|
if (*p != ':') break;
|
||||||
|
f = (int)simple_strtoul(p+1, &p, 10);
|
||||||
|
if (*p) break;
|
||||||
|
|
||||||
|
pci_dev = pci_find_slot(b, PCI_DEVFN(d,f));
|
||||||
|
if (pci_dev)
|
||||||
|
dev->hose = pci_dev->sysdata;
|
||||||
|
} while(0);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,7 @@ static drm_mem_stats_t DRM(mem_stats)[] = {
|
||||||
[DRM_MEM_MAPPINGS] = { "mappings" },
|
[DRM_MEM_MAPPINGS] = { "mappings" },
|
||||||
[DRM_MEM_BUFLISTS] = { "buflists" },
|
[DRM_MEM_BUFLISTS] = { "buflists" },
|
||||||
[DRM_MEM_AGPLISTS] = { "agplist" },
|
[DRM_MEM_AGPLISTS] = { "agplist" },
|
||||||
|
[DRM_MEM_SGLISTS] = { "sglist" },
|
||||||
[DRM_MEM_TOTALAGP] = { "totalagp" },
|
[DRM_MEM_TOTALAGP] = { "totalagp" },
|
||||||
[DRM_MEM_BOUNDAGP] = { "boundagp" },
|
[DRM_MEM_BOUNDAGP] = { "boundagp" },
|
||||||
[DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
|
[DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
|
||||||
|
|
|
@ -0,0 +1,218 @@
|
||||||
|
/* drm_scatter.h -- IOCTLs to manage scatter/gather memory -*- linux-c -*-
|
||||||
|
* Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com
|
||||||
|
*
|
||||||
|
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||||
|
* 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
|
||||||
|
* 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:
|
||||||
|
* Gareth Hughes <gareth@valinux.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define __NO_VERSION__
|
||||||
|
#include <linux/config.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include "drmP.h"
|
||||||
|
|
||||||
|
#define DEBUG_SCATTER 0
|
||||||
|
|
||||||
|
void DRM(sg_cleanup)( drm_sg_mem_t *entry )
|
||||||
|
{
|
||||||
|
struct page *page;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for ( i = 0 ; i < entry->pages ; i++ ) {
|
||||||
|
page = entry->pagelist[i];
|
||||||
|
if ( page )
|
||||||
|
ClearPageReserved( page );
|
||||||
|
}
|
||||||
|
|
||||||
|
vfree( entry->virtual );
|
||||||
|
|
||||||
|
DRM(free)( entry->pagelist,
|
||||||
|
entry->pages * sizeof(*entry->pagelist),
|
||||||
|
DRM_MEM_PAGES );
|
||||||
|
DRM(free)( entry,
|
||||||
|
sizeof(*entry),
|
||||||
|
DRM_MEM_SGLISTS );
|
||||||
|
}
|
||||||
|
|
||||||
|
int DRM(sg_alloc)( struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg )
|
||||||
|
{
|
||||||
|
drm_file_t *priv = filp->private_data;
|
||||||
|
drm_device_t *dev = priv->dev;
|
||||||
|
drm_scatter_gather_t request;
|
||||||
|
drm_sg_mem_t *entry;
|
||||||
|
unsigned long pages, i, j;
|
||||||
|
pgd_t *pgd;
|
||||||
|
pmd_t *pmd;
|
||||||
|
pte_t *pte;
|
||||||
|
|
||||||
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
|
if ( dev->sg )
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if ( copy_from_user( &request,
|
||||||
|
(drm_scatter_gather_t *)arg,
|
||||||
|
sizeof(request) ) )
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
entry = DRM(alloc)( sizeof(*entry), DRM_MEM_SGLISTS );
|
||||||
|
if ( !entry )
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
memset( entry, 0, sizeof(*entry) );
|
||||||
|
|
||||||
|
pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||||
|
DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages );
|
||||||
|
|
||||||
|
entry->pages = pages;
|
||||||
|
entry->pagelist = DRM(alloc)( pages * sizeof(*entry->pagelist),
|
||||||
|
DRM_MEM_PAGES );
|
||||||
|
if ( !entry->pagelist ) {
|
||||||
|
DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS );
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->virtual = vmalloc_32( pages << PAGE_SHIFT );
|
||||||
|
if ( !entry->virtual ) {
|
||||||
|
DRM(free)( entry->pagelist,
|
||||||
|
entry->pages * sizeof(*entry->pagelist),
|
||||||
|
DRM_MEM_PAGES );
|
||||||
|
DRM(free)( entry,
|
||||||
|
sizeof(*entry),
|
||||||
|
DRM_MEM_SGLISTS );
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This also forces the mapping of COW pages, so our page list
|
||||||
|
* will be valid. Please don't remove it...
|
||||||
|
*/
|
||||||
|
memset( entry->virtual, 0, pages << PAGE_SHIFT );
|
||||||
|
|
||||||
|
entry->handle = (unsigned long)entry->virtual;
|
||||||
|
|
||||||
|
DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle );
|
||||||
|
DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual );
|
||||||
|
|
||||||
|
for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) {
|
||||||
|
pgd = pgd_offset_k( i );
|
||||||
|
if ( !pgd_present( *pgd ) )
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
pmd = pmd_offset( pgd, i );
|
||||||
|
if ( !pmd_present( *pmd ) )
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
pte = pte_offset( pmd, i );
|
||||||
|
if ( !pte_present( *pte ) )
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
entry->pagelist[j] = pte_page( *pte );
|
||||||
|
|
||||||
|
SetPageReserved( entry->pagelist[j] );
|
||||||
|
}
|
||||||
|
|
||||||
|
request.handle = entry->handle;
|
||||||
|
|
||||||
|
if ( copy_to_user( (drm_scatter_gather_t *)arg,
|
||||||
|
&request,
|
||||||
|
sizeof(request) ) ) {
|
||||||
|
DRM(sg_cleanup)( entry );
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->sg = entry;
|
||||||
|
|
||||||
|
#if DEBUG_SCATTER
|
||||||
|
/* Verify that each page points to its virtual address, and vice
|
||||||
|
* versa.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
for ( i = 0 ; i < pages ; i++ ) {
|
||||||
|
unsigned long *tmp;
|
||||||
|
|
||||||
|
tmp = (unsigned long *)entry->pagelist[i]->virtual;
|
||||||
|
for ( j = 0 ;
|
||||||
|
j < PAGE_SIZE / sizeof(unsigned long) ;
|
||||||
|
j++, tmp++ ) {
|
||||||
|
*tmp = 0xcafebabe;
|
||||||
|
}
|
||||||
|
tmp = (unsigned long *)((u8 *)entry->virtual +
|
||||||
|
(PAGE_SIZE * i));
|
||||||
|
for( j = 0 ;
|
||||||
|
j < PAGE_SIZE / sizeof(unsigned long) ;
|
||||||
|
j++, tmp++ ) {
|
||||||
|
if ( *tmp != 0xcafebabe && error == 0 ) {
|
||||||
|
error = 1;
|
||||||
|
DRM_ERROR( "Scatter allocation error, "
|
||||||
|
"pagelist does not match "
|
||||||
|
"virtual mapping\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmp = (unsigned long *)entry->pagelist[i]->virtual;
|
||||||
|
for(j = 0 ;
|
||||||
|
j < PAGE_SIZE / sizeof(unsigned long) ;
|
||||||
|
j++, tmp++) {
|
||||||
|
*tmp = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (error == 0)
|
||||||
|
DRM_ERROR( "Scatter allocation matches pagelist\n" );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
DRM(sg_cleanup)( entry );
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DRM(sg_free)( struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg )
|
||||||
|
{
|
||||||
|
drm_file_t *priv = filp->private_data;
|
||||||
|
drm_device_t *dev = priv->dev;
|
||||||
|
drm_scatter_gather_t request;
|
||||||
|
drm_sg_mem_t *entry;
|
||||||
|
|
||||||
|
if ( copy_from_user( &request,
|
||||||
|
(drm_scatter_gather_t *)arg,
|
||||||
|
sizeof(request) ) )
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
entry = dev->sg;
|
||||||
|
dev->sg = NULL;
|
||||||
|
|
||||||
|
if ( !entry || entry->handle != request.handle )
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
DRM_DEBUG( "sg free virtual = %p\n", entry->virtual );
|
||||||
|
|
||||||
|
DRM(sg_cleanup)( entry );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -50,6 +50,12 @@ struct vm_operations_struct drm_vm_dma_ops = {
|
||||||
close: DRM(vm_close),
|
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),
|
||||||
|
};
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < 0x020317
|
#if LINUX_VERSION_CODE < 0x020317
|
||||||
unsigned long DRM(vm_nopage)(struct vm_area_struct *vma,
|
unsigned long DRM(vm_nopage)(struct vm_area_struct *vma,
|
||||||
unsigned long address,
|
unsigned long address,
|
||||||
|
@ -93,7 +99,7 @@ struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
|
||||||
offset = address - vma->vm_start;
|
offset = address - vma->vm_start;
|
||||||
i = (unsigned long)map->handle + offset;
|
i = (unsigned long)map->handle + offset;
|
||||||
/* We have to walk page tables here because we need large SAREA's, and
|
/* We have to walk page tables here because we need large SAREA's, and
|
||||||
* they need to be virtually contigious in kernel space.
|
* they need to be virtually contiguous in kernel space.
|
||||||
*/
|
*/
|
||||||
pgd = pgd_offset_k( i );
|
pgd = pgd_offset_k( i );
|
||||||
if( !pgd_present( *pgd ) ) return NOPAGE_OOM;
|
if( !pgd_present( *pgd ) ) return NOPAGE_OOM;
|
||||||
|
@ -187,6 +193,7 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
|
||||||
vfree(map->handle);
|
vfree(map->handle);
|
||||||
break;
|
break;
|
||||||
case _DRM_AGP:
|
case _DRM_AGP:
|
||||||
|
case _DRM_SCATTER_GATHER:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
|
DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
|
||||||
|
@ -230,6 +237,48 @@ struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE < 0x020317
|
||||||
|
unsigned long DRM(vm_sg_nopage)(struct vm_area_struct *vma,
|
||||||
|
unsigned long address,
|
||||||
|
int write_access)
|
||||||
|
#else
|
||||||
|
/* Return type changed in 2.3.23 */
|
||||||
|
struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
|
||||||
|
unsigned long address,
|
||||||
|
int write_access)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if LINUX_VERSION_CODE >= 0x020300
|
||||||
|
drm_map_t *map = (drm_map_t *)vma->vm_private_data;
|
||||||
|
#else
|
||||||
|
drm_map_t *map = (drm_map_t *)vma->vm_pte;
|
||||||
|
#endif
|
||||||
|
drm_file_t *priv = vma->vm_file->private_data;
|
||||||
|
drm_device_t *dev = priv->dev;
|
||||||
|
drm_sg_mem_t *entry = dev->sg;
|
||||||
|
unsigned long offset;
|
||||||
|
unsigned long map_offset;
|
||||||
|
unsigned long page_offset;
|
||||||
|
struct page *page;
|
||||||
|
|
||||||
|
if (!entry) return NOPAGE_SIGBUS; /* Error */
|
||||||
|
if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
|
||||||
|
if (!entry->pagelist) return NOPAGE_OOM ; /* Nothing allocated */
|
||||||
|
|
||||||
|
|
||||||
|
offset = address - vma->vm_start;
|
||||||
|
map_offset = map->offset - dev->sg->handle;
|
||||||
|
page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT);
|
||||||
|
page = entry->pagelist[page_offset];
|
||||||
|
atomic_inc(&page->count); /* Dec. by kernel */
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE < 0x020317
|
||||||
|
return (unsigned long)virt_to_phys(page->virtual);
|
||||||
|
#else
|
||||||
|
return page;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void DRM(vm_open)(struct vm_area_struct *vma)
|
void DRM(vm_open)(struct vm_area_struct *vma)
|
||||||
{
|
{
|
||||||
drm_file_t *priv = vma->vm_file->private_data;
|
drm_file_t *priv = vma->vm_file->private_data;
|
||||||
|
@ -322,6 +371,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
|
||||||
drm_device_t *dev = priv->dev;
|
drm_device_t *dev = priv->dev;
|
||||||
drm_map_t *map = NULL;
|
drm_map_t *map = NULL;
|
||||||
drm_map_list_t *r_list;
|
drm_map_list_t *r_list;
|
||||||
|
unsigned long offset = 0;
|
||||||
struct list_head *list;
|
struct list_head *list;
|
||||||
|
|
||||||
DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
|
DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
|
||||||
|
@ -374,19 +424,26 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
|
||||||
}
|
}
|
||||||
#elif defined(__ia64__)
|
#elif defined(__ia64__)
|
||||||
if (map->type != _DRM_AGP)
|
if (map->type != _DRM_AGP)
|
||||||
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
|
vma->vm_page_prot =
|
||||||
|
pgprot_writecombine(vma->vm_page_prot);
|
||||||
|
#elif defined(__powerpc__)
|
||||||
|
pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE | _PAGE_GUARDED;
|
||||||
#endif
|
#endif
|
||||||
vma->vm_flags |= VM_IO; /* not in core dump */
|
vma->vm_flags |= VM_IO; /* not in core dump */
|
||||||
}
|
}
|
||||||
|
#ifdef __alpha__
|
||||||
|
offset = dev->hose->dense_mem_base -
|
||||||
|
dev->hose->mem_space->start;
|
||||||
|
#endif
|
||||||
if (remap_page_range(vma->vm_start,
|
if (remap_page_range(vma->vm_start,
|
||||||
VM_OFFSET(vma),
|
VM_OFFSET(vma) + offset,
|
||||||
vma->vm_end - vma->vm_start,
|
vma->vm_end - vma->vm_start,
|
||||||
vma->vm_page_prot))
|
vma->vm_page_prot))
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx,"
|
DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx,"
|
||||||
" offset = 0x%lx\n",
|
" offset = 0x%lx\n",
|
||||||
map->type,
|
map->type,
|
||||||
vma->vm_start, vma->vm_end, VM_OFFSET(vma));
|
vma->vm_start, vma->vm_end, VM_OFFSET(vma) + offset);
|
||||||
vma->vm_ops = &drm_vm_ops;
|
vma->vm_ops = &drm_vm_ops;
|
||||||
break;
|
break;
|
||||||
case _DRM_SHM:
|
case _DRM_SHM:
|
||||||
|
@ -400,6 +457,15 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
|
||||||
DRM_KERNEL advisory is supported. */
|
DRM_KERNEL advisory is supported. */
|
||||||
vma->vm_flags |= VM_LOCKED;
|
vma->vm_flags |= VM_LOCKED;
|
||||||
break;
|
break;
|
||||||
|
case _DRM_SCATTER_GATHER:
|
||||||
|
vma->vm_ops = &drm_vm_sg_ops;
|
||||||
|
#if LINUX_VERSION_CODE >= 0x020300
|
||||||
|
vma->vm_private_data = (void *)map;
|
||||||
|
#else
|
||||||
|
vma->vm_pte = (unsigned long)map;
|
||||||
|
#endif
|
||||||
|
vma->vm_flags |= VM_LOCKED;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL; /* This should never happen. */
|
return -EINVAL; /* This should never happen. */
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,16 +33,17 @@
|
||||||
#include "r128.h"
|
#include "r128.h"
|
||||||
#include "drmP.h"
|
#include "drmP.h"
|
||||||
#include "r128_drv.h"
|
#include "r128_drv.h"
|
||||||
|
#include "ati_pcigart.h"
|
||||||
|
|
||||||
#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc."
|
#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc."
|
||||||
|
|
||||||
#define DRIVER_NAME "r128"
|
#define DRIVER_NAME "r128"
|
||||||
#define DRIVER_DESC "ATI Rage 128"
|
#define DRIVER_DESC "ATI Rage 128"
|
||||||
#define DRIVER_DATE "20010308"
|
#define DRIVER_DATE "20010405"
|
||||||
|
|
||||||
#define DRIVER_MAJOR 2
|
#define DRIVER_MAJOR 2
|
||||||
#define DRIVER_MINOR 1
|
#define DRIVER_MINOR 1
|
||||||
#define DRIVER_PATCHLEVEL 5
|
#define DRIVER_PATCHLEVEL 6
|
||||||
|
|
||||||
#define DRIVER_IOCTLS \
|
#define DRIVER_IOCTLS \
|
||||||
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { r128_cce_buffers, 1, 0 }, \
|
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { r128_cce_buffers, 1, 0 }, \
|
||||||
|
@ -88,3 +89,4 @@
|
||||||
#include "drm_proc.h"
|
#include "drm_proc.h"
|
||||||
#include "drm_vm.h"
|
#include "drm_vm.h"
|
||||||
#include "drm_stub.h"
|
#include "drm_stub.h"
|
||||||
|
#include "drm_scatter.h"
|
||||||
|
|
|
@ -31,16 +31,17 @@
|
||||||
#include "radeon.h"
|
#include "radeon.h"
|
||||||
#include "drmP.h"
|
#include "drmP.h"
|
||||||
#include "radeon_drv.h"
|
#include "radeon_drv.h"
|
||||||
|
#include "ati_pcigart.h"
|
||||||
|
|
||||||
#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc."
|
#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc."
|
||||||
|
|
||||||
#define DRIVER_NAME "radeon"
|
#define DRIVER_NAME "radeon"
|
||||||
#define DRIVER_DESC "ATI Radeon"
|
#define DRIVER_DESC "ATI Radeon"
|
||||||
#define DRIVER_DATE "20010402"
|
#define DRIVER_DATE "20010405"
|
||||||
|
|
||||||
#define DRIVER_MAJOR 1
|
#define DRIVER_MAJOR 1
|
||||||
#define DRIVER_MINOR 1
|
#define DRIVER_MINOR 1
|
||||||
#define DRIVER_PATCHLEVEL 0
|
#define DRIVER_PATCHLEVEL 1
|
||||||
|
|
||||||
#define DRIVER_IOCTLS \
|
#define DRIVER_IOCTLS \
|
||||||
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \
|
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \
|
||||||
|
@ -85,3 +86,4 @@
|
||||||
#include "drm_proc.h"
|
#include "drm_proc.h"
|
||||||
#include "drm_vm.h"
|
#include "drm_vm.h"
|
||||||
#include "drm_stub.h"
|
#include "drm_stub.h"
|
||||||
|
#include "drm_scatter.h"
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
|
|
||||||
# **** End of SMP/MODVERSIONS detection
|
# **** End of SMP/MODVERSIONS detection
|
||||||
|
|
||||||
MODS = gamma.o tdfx.o
|
MODS = gamma.o tdfx.o r128.o radeon.o
|
||||||
LIBS =
|
LIBS =
|
||||||
|
|
||||||
DRMTEMPLATES = drm_auth.h drm_bufs.h drm_context.h drm_dma.h drm_drawable.h \
|
DRMTEMPLATES = drm_auth.h drm_bufs.h drm_context.h drm_dma.h drm_drawable.h \
|
||||||
|
@ -61,6 +61,13 @@ GAMMAHEADERS = gamma_drv.h $(DRMHEADERS) $(DRMTEMPLATES)
|
||||||
TDFXOBJS = tdfx_drv.o
|
TDFXOBJS = tdfx_drv.o
|
||||||
TDFXHEADERS = tdfx.h $(DRMHEADERS)
|
TDFXHEADERS = tdfx.h $(DRMHEADERS)
|
||||||
|
|
||||||
|
R128OBJS = r128_drv.o r128_cce.o r128_state.o
|
||||||
|
R128HEADERS = r128.h r128_drv.h r128_drm.h $(DRMHEADERS) $(DRMTEMPLATES)
|
||||||
|
|
||||||
|
RADEONOBJS = radeon_drv.o radeon_cp.o radeon_state.o
|
||||||
|
RADEONHEADERS = radeon.h radeon_drv.h radeon_drm.h $(DRMHEADERS) \
|
||||||
|
$(DRMTEMPLATES)
|
||||||
|
|
||||||
INC = /usr/include
|
INC = /usr/include
|
||||||
|
|
||||||
CFLAGS = -O2 $(WARNINGS)
|
CFLAGS = -O2 $(WARNINGS)
|
||||||
|
@ -132,7 +139,7 @@ ifeq ($(AGP),1)
|
||||||
MODCFLAGS += -DCONFIG_AGP -DCONFIG_AGP_MODULE
|
MODCFLAGS += -DCONFIG_AGP -DCONFIG_AGP_MODULE
|
||||||
DRMTEMPLATES += drm_agpsupport.h
|
DRMTEMPLATES += drm_agpsupport.h
|
||||||
DRMHEADERS += agpsupport-pre24.h
|
DRMHEADERS += agpsupport-pre24.h
|
||||||
MODS += mga.o r128.o radeon.o
|
MODS += mga.o
|
||||||
ifeq ($(MACHINE),i386)
|
ifeq ($(MACHINE),i386)
|
||||||
MODS += i810.o
|
MODS += i810.o
|
||||||
endif
|
endif
|
||||||
|
@ -140,19 +147,16 @@ ifeq ($(MACHINE),i686)
|
||||||
MODS += i810.o
|
MODS += i810.o
|
||||||
endif
|
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
|
||||||
MGAHEADERS = mga.h mga_drv.h mga_drm.h $(DRMHEADERS) $(DRMTEMPLATES)
|
MGAHEADERS = mga.h mga_drv.h mga_drm.h $(DRMHEADERS) $(DRMTEMPLATES)
|
||||||
|
|
||||||
I810OBJS = i810_drv.o i810_dma.o
|
I810OBJS = i810_drv.o i810_dma.o
|
||||||
I810HEADERS = i810.h i810_drv.h i810_drm.h $(DRMHEADERS) $(DRMTEMPLATES)
|
I810HEADERS = i810.h i810_drv.h i810_drm.h $(DRMHEADERS) $(DRMTEMPLATES)
|
||||||
|
|
||||||
R128OBJS = r128_drv.o r128_cce.o r128_state.o
|
endif
|
||||||
R128HEADERS = r128.h r128_drv.h r128_drm.h $(DRMHEADERS) $(DRMTEMPLATES)
|
|
||||||
|
|
||||||
RADEONOBJS = radeon_drv.o radeon_cp.o radeon_state.o
|
ifeq ($(MACHINE),alpha)
|
||||||
RADEONHEADERS = radeon.h radeon_drv.h radeon_drm.h $(DRMHEADERS) \
|
MODCFLAGS+= -ffixed-8 -mno-fp-regs -mcpu=ev56 -Wa,-mev6
|
||||||
$(DRMTEMPLATES)
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(SIS),1)
|
ifeq ($(SIS),1)
|
||||||
|
@ -218,6 +222,16 @@ tdfx.o: $(TDFXOBJS) $(LIBS)
|
||||||
sis.o: $(SISOBJS) $(LIBS)
|
sis.o: $(SISOBJS) $(LIBS)
|
||||||
$(LD) -r $^ -o $@
|
$(LD) -r $^ -o $@
|
||||||
|
|
||||||
|
r128_drv.o: r128_drv.c
|
||||||
|
$(CC) $(MODCFLAGS) -DEXPORT_SYMTAB -I$(TREE) -c $< -o $@
|
||||||
|
r128.o: $(R128OBJS) $(LIBS)
|
||||||
|
$(LD) -r $^ -o $@
|
||||||
|
|
||||||
|
radeon_drv.o: radeon_drv.c
|
||||||
|
$(CC) $(MODCFLAGS) -DEXPORT_SYMTAB -I$(TREE) -c $< -o $@
|
||||||
|
radeon.o: $(RADEONOBJS) $(LIBS)
|
||||||
|
$(LD) -r $^ -o $@
|
||||||
|
|
||||||
ifeq ($(AGP),1)
|
ifeq ($(AGP),1)
|
||||||
mga_drv.o: mga_drv.c
|
mga_drv.o: mga_drv.c
|
||||||
$(CC) $(MODCFLAGS) -DEXPORT_SYMTAB -I$(TREE) -c $< -o $@
|
$(CC) $(MODCFLAGS) -DEXPORT_SYMTAB -I$(TREE) -c $< -o $@
|
||||||
|
@ -229,15 +243,6 @@ i810_drv.o: i810_drv.c
|
||||||
i810.o: $(I810OBJS) $(LIBS)
|
i810.o: $(I810OBJS) $(LIBS)
|
||||||
$(LD) -r $^ -o $@
|
$(LD) -r $^ -o $@
|
||||||
|
|
||||||
r128_drv.o: r128_drv.c
|
|
||||||
$(CC) $(MODCFLAGS) -DEXPORT_SYMTAB -I$(TREE) -c $< -o $@
|
|
||||||
r128.o: $(R128OBJS) $(LIBS)
|
|
||||||
$(LD) -r $^ -o $@
|
|
||||||
|
|
||||||
radeon_drv.o: radeon_drv.c
|
|
||||||
$(CC) $(MODCFLAGS) -DEXPORT_SYMTAB -I$(TREE) -c $< -o $@
|
|
||||||
radeon.o: $(RADEONOBJS) $(LIBS)
|
|
||||||
$(LD) -r $^ -o $@
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: ChangeLog
|
.PHONY: ChangeLog
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
/* ati_pcigart.h -- ATI PCI GART support -*- linux-c -*-
|
||||||
|
* Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com
|
||||||
|
*
|
||||||
|
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||||
|
* 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
|
||||||
|
* 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:
|
||||||
|
* Gareth Hughes <gareth@valinux.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define __NO_VERSION__
|
||||||
|
#include "drmP.h"
|
||||||
|
|
||||||
|
#if PAGE_SIZE == 8192
|
||||||
|
# define ATI_PCIGART_TABLE_ORDER 2
|
||||||
|
# define ATI_PCIGART_TABLE_PAGES (1 << 2)
|
||||||
|
#elif PAGE_SIZE == 4096
|
||||||
|
# define ATI_PCIGART_TABLE_ORDER 3
|
||||||
|
# define ATI_PCIGART_TABLE_PAGES (1 << 3)
|
||||||
|
#elif
|
||||||
|
# error - PAGE_SIZE not 8K or 4K
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# define ATI_MAX_PCIGART_PAGES 8192 /* 32 MB aperture, 4K pages */
|
||||||
|
# define ATI_PCIGART_PAGE_SIZE 4096 /* PCI GART page size */
|
||||||
|
|
||||||
|
static unsigned long DRM(ati_alloc_pcigart_table)( void )
|
||||||
|
{
|
||||||
|
unsigned long address;
|
||||||
|
struct page *page;
|
||||||
|
int i;
|
||||||
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
|
address = __get_free_pages( GFP_KERNEL, ATI_PCIGART_TABLE_ORDER );
|
||||||
|
if ( address == 0UL ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
page = virt_to_page( address );
|
||||||
|
|
||||||
|
for ( i = 0 ; i <= ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
|
||||||
|
atomic_inc( &page->count );
|
||||||
|
SetPageReserved( page );
|
||||||
|
}
|
||||||
|
|
||||||
|
DRM_DEBUG( "%s: returning 0x%08lx\n", __FUNCTION__, address );
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DRM(ati_free_pcigart_table)( unsigned long address )
|
||||||
|
{
|
||||||
|
struct page *page;
|
||||||
|
int i;
|
||||||
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
|
if ( !address ) return;
|
||||||
|
|
||||||
|
page = virt_to_page( address );
|
||||||
|
|
||||||
|
for ( i = 0 ; i <= ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
|
||||||
|
atomic_dec( &page->count );
|
||||||
|
ClearPageReserved( page );
|
||||||
|
}
|
||||||
|
|
||||||
|
free_pages( address, ATI_PCIGART_TABLE_ORDER );
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long DRM(ati_pcigart_init)( drm_device_t *dev )
|
||||||
|
{
|
||||||
|
drm_sg_mem_t *entry = dev->sg;
|
||||||
|
unsigned long address;
|
||||||
|
unsigned long pages;
|
||||||
|
u32 *pci_gart, page_base;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if ( !entry ) {
|
||||||
|
DRM_ERROR( "no scatter/gather memory!\n" );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
address = DRM(ati_alloc_pcigart_table)();
|
||||||
|
if ( !address ) {
|
||||||
|
DRM_ERROR( "cannot allocate PCI GART page!\n" );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pci_gart = (u32 *)address;
|
||||||
|
|
||||||
|
pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
|
||||||
|
? entry->pages : ATI_MAX_PCIGART_PAGES;
|
||||||
|
|
||||||
|
memset( pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32) );
|
||||||
|
|
||||||
|
for ( i = 0 ; i < pages ; i++ ) {
|
||||||
|
page_base = virt_to_bus( entry->pagelist[i]->virtual );
|
||||||
|
for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
|
||||||
|
*pci_gart++ = cpu_to_le32( page_base );
|
||||||
|
page_base += ATI_PCIGART_PAGE_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __i386__
|
||||||
|
asm volatile ( "wbinvd" ::: "memory" );
|
||||||
|
#else
|
||||||
|
mb();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DRM(ati_pcigart_cleanup)( unsigned long address )
|
||||||
|
{
|
||||||
|
|
||||||
|
if ( address ) {
|
||||||
|
DRM(ati_free_pcigart_table)( address );
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
20
linux/drm.h
20
linux/drm.h
|
@ -126,10 +126,11 @@ typedef struct drm_control {
|
||||||
} drm_control_t;
|
} drm_control_t;
|
||||||
|
|
||||||
typedef enum drm_map_type {
|
typedef enum drm_map_type {
|
||||||
_DRM_FRAME_BUFFER = 0, /* WC (no caching), no core dump */
|
_DRM_FRAME_BUFFER = 0, /* WC (no caching), no core dump */
|
||||||
_DRM_REGISTERS = 1, /* no caching, no core dump */
|
_DRM_REGISTERS = 1, /* no caching, no core dump */
|
||||||
_DRM_SHM = 2, /* shared, cached */
|
_DRM_SHM = 2, /* shared, cached */
|
||||||
_DRM_AGP = 3 /* AGP/GART */
|
_DRM_AGP = 3, /* AGP/GART */
|
||||||
|
_DRM_SCATTER_GATHER = 4 /* Scatter/gather memory for PCI DMA */
|
||||||
} drm_map_type_t;
|
} drm_map_type_t;
|
||||||
|
|
||||||
typedef enum drm_map_flags {
|
typedef enum drm_map_flags {
|
||||||
|
@ -238,7 +239,8 @@ typedef struct drm_buf_desc {
|
||||||
int high_mark; /* High water mark */
|
int high_mark; /* High water mark */
|
||||||
enum {
|
enum {
|
||||||
_DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA */
|
_DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA */
|
||||||
_DRM_AGP_BUFFER = 0x02 /* Buffer is in agp space */
|
_DRM_AGP_BUFFER = 0x02, /* Buffer is in agp space */
|
||||||
|
_DRM_SG_BUFFER = 0x04 /* Scatter/gather memory buffer */
|
||||||
} flags;
|
} flags;
|
||||||
unsigned long agp_start; /* Start address of where the agp buffers
|
unsigned long agp_start; /* Start address of where the agp buffers
|
||||||
* are in the agp aperture */
|
* are in the agp aperture */
|
||||||
|
@ -344,6 +346,11 @@ typedef struct drm_agp_info {
|
||||||
unsigned short id_device;
|
unsigned short id_device;
|
||||||
} drm_agp_info_t;
|
} drm_agp_info_t;
|
||||||
|
|
||||||
|
typedef struct drm_scatter_gather {
|
||||||
|
unsigned long size; /* In bytes -- will round to page boundary */
|
||||||
|
unsigned long handle; /* Used for mapping / unmapping */
|
||||||
|
} drm_scatter_gather_t;
|
||||||
|
|
||||||
#define DRM_IOCTL_BASE 'd'
|
#define DRM_IOCTL_BASE 'd'
|
||||||
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
|
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
|
||||||
#define DRM_IOR(nr,size) _IOR(DRM_IOCTL_BASE,nr,size)
|
#define DRM_IOR(nr,size) _IOR(DRM_IOCTL_BASE,nr,size)
|
||||||
|
@ -399,6 +406,9 @@ typedef struct drm_agp_info {
|
||||||
#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t)
|
#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t)
|
||||||
#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t)
|
#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t)
|
||||||
|
|
||||||
|
#define DRM_IOCTL_SG_ALLOC DRM_IOW( 0x38, drm_scatter_gather_t)
|
||||||
|
#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, drm_scatter_gather_t)
|
||||||
|
|
||||||
/* MGA specific ioctls */
|
/* MGA specific ioctls */
|
||||||
#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t)
|
#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t)
|
||||||
#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x41, drm_lock_t)
|
#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x41, drm_lock_t)
|
||||||
|
|
77
linux/drmP.h
77
linux/drmP.h
|
@ -53,7 +53,7 @@
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/smp_lock.h> /* For (un)lock_kernel */
|
#include <linux/smp_lock.h> /* For (un)lock_kernel */
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#ifdef __alpha__
|
#if defined(__alpha__) || defined(__powerpc__)
|
||||||
#include <asm/pgtable.h> /* For pte_wrprotect */
|
#include <asm/pgtable.h> /* For pte_wrprotect */
|
||||||
#endif
|
#endif
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
@ -145,6 +145,7 @@
|
||||||
#define DRM_MEM_BOUNDAGP 17
|
#define DRM_MEM_BOUNDAGP 17
|
||||||
#define DRM_MEM_CTXBITMAP 18
|
#define DRM_MEM_CTXBITMAP 18
|
||||||
#define DRM_MEM_STUB 19
|
#define DRM_MEM_STUB 19
|
||||||
|
#define DRM_MEM_SGLISTS 20
|
||||||
|
|
||||||
#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
|
#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
|
||||||
|
|
||||||
|
@ -199,7 +200,7 @@ __cmpxchg_u32(volatile int *m, int old, int new)
|
||||||
unsigned long prev, cmp;
|
unsigned long prev, cmp;
|
||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
"1: ldl_l %0,%2\n"
|
"1: ldl_l %0,%5\n"
|
||||||
" cmpeq %0,%3,%1\n"
|
" cmpeq %0,%3,%1\n"
|
||||||
" beq %1,2f\n"
|
" beq %1,2f\n"
|
||||||
" mov %4,%1\n"
|
" mov %4,%1\n"
|
||||||
|
@ -210,7 +211,8 @@ __cmpxchg_u32(volatile int *m, int old, int new)
|
||||||
"3: br 1b\n"
|
"3: br 1b\n"
|
||||||
".previous"
|
".previous"
|
||||||
: "=&r"(prev), "=&r"(cmp), "=m"(*m)
|
: "=&r"(prev), "=&r"(cmp), "=m"(*m)
|
||||||
: "r"((long) old), "r"(new), "m"(*m));
|
: "r"((long) old), "r"(new), "m"(*m)
|
||||||
|
: "memory" );
|
||||||
|
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
@ -221,7 +223,7 @@ __cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
|
||||||
unsigned long prev, cmp;
|
unsigned long prev, cmp;
|
||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
"1: ldq_l %0,%2\n"
|
"1: ldq_l %0,%5\n"
|
||||||
" cmpeq %0,%3,%1\n"
|
" cmpeq %0,%3,%1\n"
|
||||||
" beq %1,2f\n"
|
" beq %1,2f\n"
|
||||||
" mov %4,%1\n"
|
" mov %4,%1\n"
|
||||||
|
@ -232,7 +234,8 @@ __cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
|
||||||
"3: br 1b\n"
|
"3: br 1b\n"
|
||||||
".previous"
|
".previous"
|
||||||
: "=&r"(prev), "=&r"(cmp), "=m"(*m)
|
: "=&r"(prev), "=&r"(cmp), "=m"(*m)
|
||||||
: "r"((long) old), "r"(new), "m"(*m));
|
: "r"((long) old), "r"(new), "m"(*m)
|
||||||
|
: "memory" );
|
||||||
|
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
@ -284,12 +287,43 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(__powerpc__)
|
||||||
|
extern void __cmpxchg_called_with_bad_pointer(void);
|
||||||
|
static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
|
||||||
|
unsigned long new, int size)
|
||||||
|
{
|
||||||
|
unsigned long prev;
|
||||||
|
|
||||||
|
switch (size) {
|
||||||
|
case 4:
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"sync;"
|
||||||
|
"0: lwarx %0,0,%1 ;"
|
||||||
|
" cmpl 0,%0,%3;"
|
||||||
|
" bne 1f;"
|
||||||
|
" stwcx. %2,0,%1;"
|
||||||
|
" bne- 0b;"
|
||||||
|
"1: "
|
||||||
|
"sync;"
|
||||||
|
: "=&r"(prev)
|
||||||
|
: "r"(ptr), "r"(new), "r"(old)
|
||||||
|
: "cr0", "memory");
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
__cmpxchg_called_with_bad_pointer();
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* i386, powerpc & alpha */
|
||||||
|
|
||||||
|
#ifndef __alpha__
|
||||||
#define cmpxchg(ptr,o,n) \
|
#define cmpxchg(ptr,o,n) \
|
||||||
((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o), \
|
((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o), \
|
||||||
(unsigned long)(n),sizeof(*(ptr))))
|
(unsigned long)(n),sizeof(*(ptr))))
|
||||||
#endif /* i386 & alpha */
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* !__HAVE_ARCH_CMPXCHG */
|
||||||
|
|
||||||
/* Macros to make printk easier */
|
/* Macros to make printk easier */
|
||||||
#define DRM_ERROR(fmt, arg...) \
|
#define DRM_ERROR(fmt, arg...) \
|
||||||
printk(KERN_ERR "[" DRM_NAME ":" __FUNCTION__ "] *ERROR* " fmt , ##arg)
|
printk(KERN_ERR "[" DRM_NAME ":" __FUNCTION__ "] *ERROR* " fmt , ##arg)
|
||||||
|
@ -547,7 +581,8 @@ typedef struct drm_device_dma {
|
||||||
unsigned long *pagelist;
|
unsigned long *pagelist;
|
||||||
unsigned long byte_count;
|
unsigned long byte_count;
|
||||||
enum {
|
enum {
|
||||||
_DRM_DMA_USE_AGP = 0x01
|
_DRM_DMA_USE_AGP = 0x01,
|
||||||
|
_DRM_DMA_USE_SG = 0x02
|
||||||
} flags;
|
} flags;
|
||||||
|
|
||||||
/* DMA support */
|
/* DMA support */
|
||||||
|
@ -579,6 +614,13 @@ typedef struct drm_agp_head {
|
||||||
} drm_agp_head_t;
|
} drm_agp_head_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef struct drm_sg_mem {
|
||||||
|
unsigned long handle;
|
||||||
|
void *virtual;
|
||||||
|
int pages;
|
||||||
|
struct page **pagelist;
|
||||||
|
} drm_sg_mem_t;
|
||||||
|
|
||||||
typedef struct drm_sigdata {
|
typedef struct drm_sigdata {
|
||||||
int context;
|
int context;
|
||||||
drm_hw_lock_t *lock;
|
drm_hw_lock_t *lock;
|
||||||
|
@ -667,6 +709,10 @@ typedef struct drm_device {
|
||||||
#if __REALLY_HAVE_AGP
|
#if __REALLY_HAVE_AGP
|
||||||
drm_agp_head_t *agp;
|
drm_agp_head_t *agp;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef __alpha__
|
||||||
|
struct pci_controler *hose;
|
||||||
|
#endif
|
||||||
|
drm_sg_mem_t *sg; /* Scatter gather memory */
|
||||||
unsigned long *ctx_bitmap;
|
unsigned long *ctx_bitmap;
|
||||||
void *dev_private;
|
void *dev_private;
|
||||||
drm_sigdata_t sigdata; /* For block_all_signals */
|
drm_sigdata_t sigdata; /* For block_all_signals */
|
||||||
|
@ -718,6 +764,9 @@ extern unsigned long DRM(vm_shm_nopage)(struct vm_area_struct *vma,
|
||||||
extern unsigned long DRM(vm_dma_nopage)(struct vm_area_struct *vma,
|
extern unsigned long DRM(vm_dma_nopage)(struct vm_area_struct *vma,
|
||||||
unsigned long address,
|
unsigned long address,
|
||||||
int write_access);
|
int write_access);
|
||||||
|
extern unsigned long DRM(vm_sg_nopage)(struct vm_area_struct *vma,
|
||||||
|
unsigned long address,
|
||||||
|
int write_access);
|
||||||
#else
|
#else
|
||||||
/* Return type changed in 2.3.23 */
|
/* Return type changed in 2.3.23 */
|
||||||
extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
|
extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
|
||||||
|
@ -729,6 +778,9 @@ extern struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
|
||||||
extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
|
extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
|
||||||
unsigned long address,
|
unsigned long address,
|
||||||
int write_access);
|
int write_access);
|
||||||
|
extern struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
|
||||||
|
unsigned long address,
|
||||||
|
int write_access);
|
||||||
#endif
|
#endif
|
||||||
extern void DRM(vm_open)(struct vm_area_struct *vma);
|
extern void DRM(vm_open)(struct vm_area_struct *vma);
|
||||||
extern void DRM(vm_close)(struct vm_area_struct *vma);
|
extern void DRM(vm_close)(struct vm_area_struct *vma);
|
||||||
|
@ -947,5 +999,16 @@ extern int DRM(proc_cleanup)(int minor,
|
||||||
struct proc_dir_entry *root,
|
struct proc_dir_entry *root,
|
||||||
struct proc_dir_entry *dev_root);
|
struct proc_dir_entry *dev_root);
|
||||||
|
|
||||||
|
/* Scatter Gather Support (drm_scatter.h) */
|
||||||
|
extern void DRM(sg_cleanup)(drm_sg_mem_t *entry);
|
||||||
|
extern int DRM(sg_alloc)(struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
extern int DRM(sg_free)(struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
|
||||||
|
/* ATI PCIGART support (ati_pcigart.h) */
|
||||||
|
extern unsigned long DRM(ati_pcigart_init)(drm_device_t *dev);
|
||||||
|
extern int DRM(ati_pcigart_cleanup)(unsigned long address);
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -52,7 +52,8 @@ int DRM(agp_info)(struct inode *inode, struct file *filp,
|
||||||
agp_kern_info *kern;
|
agp_kern_info *kern;
|
||||||
drm_agp_info_t info;
|
drm_agp_info_t info;
|
||||||
|
|
||||||
if (!dev->agp->acquired || !drm_agp->copy_info) return -EINVAL;
|
if (!dev->agp || !dev->agp->acquired || !drm_agp->copy_info)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
kern = &dev->agp->agp_info;
|
kern = &dev->agp->agp_info;
|
||||||
info.agp_version_major = kern->version.major;
|
info.agp_version_major = kern->version.major;
|
||||||
|
@ -77,7 +78,8 @@ int DRM(agp_acquire)(struct inode *inode, struct file *filp,
|
||||||
drm_device_t *dev = priv->dev;
|
drm_device_t *dev = priv->dev;
|
||||||
int retcode;
|
int retcode;
|
||||||
|
|
||||||
if (!dev->agp|| dev->agp->acquired || !drm_agp->acquire) return -EINVAL;
|
if (!dev->agp || dev->agp->acquired || !drm_agp->acquire)
|
||||||
|
return -EINVAL;
|
||||||
if ((retcode = drm_agp->acquire())) return retcode;
|
if ((retcode = drm_agp->acquire())) return retcode;
|
||||||
dev->agp->acquired = 1;
|
dev->agp->acquired = 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -89,7 +91,8 @@ int DRM(agp_release)(struct inode *inode, struct file *filp,
|
||||||
drm_file_t *priv = filp->private_data;
|
drm_file_t *priv = filp->private_data;
|
||||||
drm_device_t *dev = priv->dev;
|
drm_device_t *dev = priv->dev;
|
||||||
|
|
||||||
if (!dev->agp->acquired || !drm_agp->release) return -EINVAL;
|
if (!dev->agp || !dev->agp->acquired || !drm_agp->release)
|
||||||
|
return -EINVAL;
|
||||||
drm_agp->release();
|
drm_agp->release();
|
||||||
dev->agp->acquired = 0;
|
dev->agp->acquired = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -108,7 +111,8 @@ int DRM(agp_enable)(struct inode *inode, struct file *filp,
|
||||||
drm_device_t *dev = priv->dev;
|
drm_device_t *dev = priv->dev;
|
||||||
drm_agp_mode_t mode;
|
drm_agp_mode_t mode;
|
||||||
|
|
||||||
if (!dev->agp->acquired || !drm_agp->enable) return -EINVAL;
|
if (!dev->agp || !dev->agp->acquired || !drm_agp->enable)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
if (copy_from_user(&mode, (drm_agp_mode_t *)arg, sizeof(mode)))
|
if (copy_from_user(&mode, (drm_agp_mode_t *)arg, sizeof(mode)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
@ -131,7 +135,7 @@ int DRM(agp_alloc)(struct inode *inode, struct file *filp,
|
||||||
unsigned long pages;
|
unsigned long pages;
|
||||||
u32 type;
|
u32 type;
|
||||||
|
|
||||||
if (!dev->agp->acquired) return -EINVAL;
|
if (!dev->agp || !dev->agp->acquired) return -EINVAL;
|
||||||
if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
|
if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (!(entry = DRM(alloc)(sizeof(*entry), DRM_MEM_AGPLISTS)))
|
if (!(entry = DRM(alloc)(sizeof(*entry), DRM_MEM_AGPLISTS)))
|
||||||
|
@ -188,7 +192,7 @@ int DRM(agp_unbind)(struct inode *inode, struct file *filp,
|
||||||
drm_agp_binding_t request;
|
drm_agp_binding_t request;
|
||||||
drm_agp_mem_t *entry;
|
drm_agp_mem_t *entry;
|
||||||
|
|
||||||
if (!dev->agp->acquired) return -EINVAL;
|
if (!dev->agp || !dev->agp->acquired) return -EINVAL;
|
||||||
if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
|
if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
|
if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
|
||||||
|
@ -207,7 +211,8 @@ int DRM(agp_bind)(struct inode *inode, struct file *filp,
|
||||||
int retcode;
|
int retcode;
|
||||||
int page;
|
int page;
|
||||||
|
|
||||||
if (!dev->agp->acquired || !drm_agp->bind_memory) return -EINVAL;
|
if (!dev->agp || !dev->agp->acquired || !drm_agp->bind_memory)
|
||||||
|
return -EINVAL;
|
||||||
if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
|
if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
|
if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
|
||||||
|
@ -229,7 +234,7 @@ int DRM(agp_free)(struct inode *inode, struct file *filp,
|
||||||
drm_agp_buffer_t request;
|
drm_agp_buffer_t request;
|
||||||
drm_agp_mem_t *entry;
|
drm_agp_mem_t *entry;
|
||||||
|
|
||||||
if (!dev->agp->acquired) return -EINVAL;
|
if (!dev->agp || !dev->agp->acquired) return -EINVAL;
|
||||||
if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
|
if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
|
if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
|
||||||
|
|
182
linux/drm_bufs.h
182
linux/drm_bufs.h
|
@ -37,6 +37,10 @@
|
||||||
#define __HAVE_PCI_DMA 0
|
#define __HAVE_PCI_DMA 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __HAVE_SG
|
||||||
|
#define __HAVE_SG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef DRIVER_BUF_PRIV_T
|
#ifndef DRIVER_BUF_PRIV_T
|
||||||
#define DRIVER_BUF_PRIV_T u32
|
#define DRIVER_BUF_PRIV_T u32
|
||||||
#endif
|
#endif
|
||||||
|
@ -103,13 +107,16 @@ int DRM(addmap)( struct inode *inode, struct file *filp,
|
||||||
switch ( map->type ) {
|
switch ( map->type ) {
|
||||||
case _DRM_REGISTERS:
|
case _DRM_REGISTERS:
|
||||||
case _DRM_FRAME_BUFFER:
|
case _DRM_FRAME_BUFFER:
|
||||||
#ifndef __sparc__
|
#if !defined(__sparc__) && !defined(__alpha__)
|
||||||
if ( map->offset + map->size < map->offset ||
|
if ( map->offset + map->size < map->offset ||
|
||||||
map->offset < virt_to_phys(high_memory) ) {
|
map->offset < virt_to_phys(high_memory) ) {
|
||||||
DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
|
DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef __alpha__
|
||||||
|
map->offset += dev->hose->mem_space->start;
|
||||||
|
#endif
|
||||||
#if __REALLY_HAVE_MTRR
|
#if __REALLY_HAVE_MTRR
|
||||||
if ( map->type == _DRM_FRAME_BUFFER ||
|
if ( map->type == _DRM_FRAME_BUFFER ||
|
||||||
(map->flags & _DRM_WRITE_COMBINING) ) {
|
(map->flags & _DRM_WRITE_COMBINING) ) {
|
||||||
|
@ -135,10 +142,21 @@ int DRM(addmap)( struct inode *inode, struct file *filp,
|
||||||
break;
|
break;
|
||||||
#if __REALLY_HAVE_AGP
|
#if __REALLY_HAVE_AGP
|
||||||
case _DRM_AGP:
|
case _DRM_AGP:
|
||||||
|
#ifdef __alpha__
|
||||||
|
map->offset += dev->hose->mem_space->start;
|
||||||
|
#endif
|
||||||
map->offset = map->offset + dev->agp->base;
|
map->offset = map->offset + dev->agp->base;
|
||||||
map->mtrr = dev->agp->agp_mtrr; /* for getmap */
|
map->mtrr = dev->agp->agp_mtrr; /* for getmap */
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
case _DRM_SCATTER_GATHER:
|
||||||
|
if (!dev->sg) {
|
||||||
|
DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
map->offset = map->offset + dev->sg->handle;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
|
DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -237,6 +255,7 @@ int DRM(rmmap)(struct inode *inode, struct file *filp,
|
||||||
vfree(map->handle);
|
vfree(map->handle);
|
||||||
break;
|
break;
|
||||||
case _DRM_AGP:
|
case _DRM_AGP:
|
||||||
|
case _DRM_SCATTER_GATHER:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
|
DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
|
||||||
|
@ -565,6 +584,159 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp,
|
||||||
}
|
}
|
||||||
#endif /* __HAVE_PCI_DMA */
|
#endif /* __HAVE_PCI_DMA */
|
||||||
|
|
||||||
|
#ifdef __HAVE_SG
|
||||||
|
int DRM(addbufs_sg)( struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg )
|
||||||
|
{
|
||||||
|
drm_file_t *priv = filp->private_data;
|
||||||
|
drm_device_t *dev = priv->dev;
|
||||||
|
drm_device_dma_t *dma = dev->dma;
|
||||||
|
drm_buf_desc_t request;
|
||||||
|
drm_buf_entry_t *entry;
|
||||||
|
drm_buf_t *buf;
|
||||||
|
unsigned long offset;
|
||||||
|
unsigned long agp_offset;
|
||||||
|
int count;
|
||||||
|
int order;
|
||||||
|
int size;
|
||||||
|
int alignment;
|
||||||
|
int page_order;
|
||||||
|
int total;
|
||||||
|
int byte_count;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ( !dma ) return -EINVAL;
|
||||||
|
|
||||||
|
if ( copy_from_user( &request, (drm_buf_desc_t *)arg,
|
||||||
|
sizeof(request) ) )
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
count = request.count;
|
||||||
|
order = DRM(order)( request.size );
|
||||||
|
size = 1 << order;
|
||||||
|
|
||||||
|
alignment = (request.flags & _DRM_PAGE_ALIGN)
|
||||||
|
? PAGE_ALIGN(size) : size;
|
||||||
|
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
|
||||||
|
total = PAGE_SIZE << page_order;
|
||||||
|
|
||||||
|
byte_count = 0;
|
||||||
|
agp_offset = request.agp_start;
|
||||||
|
|
||||||
|
DRM_DEBUG( "count: %d\n", count );
|
||||||
|
DRM_DEBUG( "order: %d\n", order );
|
||||||
|
DRM_DEBUG( "size: %d\n", size );
|
||||||
|
DRM_DEBUG( "agp_offset: %ld\n", agp_offset );
|
||||||
|
DRM_DEBUG( "alignment: %d\n", alignment );
|
||||||
|
DRM_DEBUG( "page_order: %d\n", page_order );
|
||||||
|
DRM_DEBUG( "total: %d\n", total );
|
||||||
|
|
||||||
|
if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
|
||||||
|
if ( dev->queue_count ) return -EBUSY; /* Not while in use */
|
||||||
|
|
||||||
|
spin_lock( &dev->count_lock );
|
||||||
|
if ( dev->buf_use ) {
|
||||||
|
spin_unlock( &dev->count_lock );
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
atomic_inc( &dev->buf_alloc );
|
||||||
|
spin_unlock( &dev->count_lock );
|
||||||
|
|
||||||
|
down( &dev->struct_sem );
|
||||||
|
entry = &dma->bufs[order];
|
||||||
|
if ( entry->buf_count ) {
|
||||||
|
up( &dev->struct_sem );
|
||||||
|
atomic_dec( &dev->buf_alloc );
|
||||||
|
return -ENOMEM; /* May only call once for each order */
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist),
|
||||||
|
DRM_MEM_BUFS );
|
||||||
|
if ( !entry->buflist ) {
|
||||||
|
up( &dev->struct_sem );
|
||||||
|
atomic_dec( &dev->buf_alloc );
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
|
||||||
|
|
||||||
|
entry->buf_size = size;
|
||||||
|
entry->page_order = page_order;
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
|
while ( entry->buf_count < count ) {
|
||||||
|
buf = &entry->buflist[entry->buf_count];
|
||||||
|
buf->idx = dma->buf_count + entry->buf_count;
|
||||||
|
buf->total = alignment;
|
||||||
|
buf->order = order;
|
||||||
|
buf->used = 0;
|
||||||
|
|
||||||
|
buf->offset = (dma->byte_count + offset);
|
||||||
|
buf->bus_address = agp_offset + offset;
|
||||||
|
buf->address = (void *)(agp_offset + offset + dev->sg->handle);
|
||||||
|
buf->next = NULL;
|
||||||
|
buf->waiting = 0;
|
||||||
|
buf->pending = 0;
|
||||||
|
init_waitqueue_head( &buf->dma_wait );
|
||||||
|
buf->pid = 0;
|
||||||
|
|
||||||
|
buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T);
|
||||||
|
buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T),
|
||||||
|
DRM_MEM_BUFS );
|
||||||
|
memset( buf->dev_private, 0, buf->dev_priv_size );
|
||||||
|
|
||||||
|
#if __HAVE_DMA_HISTOGRAM
|
||||||
|
buf->time_queued = 0;
|
||||||
|
buf->time_dispatched = 0;
|
||||||
|
buf->time_completed = 0;
|
||||||
|
buf->time_freed = 0;
|
||||||
|
#endif
|
||||||
|
DRM_DEBUG( "buffer %d @ %p\n",
|
||||||
|
entry->buf_count, buf->address );
|
||||||
|
|
||||||
|
offset += alignment;
|
||||||
|
entry->buf_count++;
|
||||||
|
byte_count += PAGE_SIZE << page_order;
|
||||||
|
}
|
||||||
|
|
||||||
|
DRM_DEBUG( "byte_count: %d\n", byte_count );
|
||||||
|
|
||||||
|
dma->buflist = DRM(realloc)( dma->buflist,
|
||||||
|
dma->buf_count * sizeof(*dma->buflist),
|
||||||
|
(dma->buf_count + entry->buf_count)
|
||||||
|
* sizeof(*dma->buflist),
|
||||||
|
DRM_MEM_BUFS );
|
||||||
|
for ( i = 0 ; i < entry->buf_count ; i++ ) {
|
||||||
|
dma->buflist[i + dma->buf_count] = &entry->buflist[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
dma->buf_count += entry->buf_count;
|
||||||
|
dma->byte_count += byte_count;
|
||||||
|
|
||||||
|
DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
|
||||||
|
DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
|
||||||
|
|
||||||
|
#if __HAVE_DMA_FREELIST
|
||||||
|
DRM(freelist_create)( &entry->freelist, entry->buf_count );
|
||||||
|
for ( i = 0 ; i < entry->buf_count ; i++ ) {
|
||||||
|
DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
up( &dev->struct_sem );
|
||||||
|
|
||||||
|
request.count = entry->buf_count;
|
||||||
|
request.size = size;
|
||||||
|
|
||||||
|
if ( copy_to_user( (drm_buf_desc_t *)arg, &request, sizeof(request) ) )
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
dma->flags = _DRM_DMA_USE_SG;
|
||||||
|
|
||||||
|
atomic_dec( &dev->buf_alloc );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* __HAVE_SG */
|
||||||
|
|
||||||
int DRM(addbufs)( struct inode *inode, struct file *filp,
|
int DRM(addbufs)( struct inode *inode, struct file *filp,
|
||||||
unsigned int cmd, unsigned long arg )
|
unsigned int cmd, unsigned long arg )
|
||||||
{
|
{
|
||||||
|
@ -579,6 +751,11 @@ int DRM(addbufs)( struct inode *inode, struct file *filp,
|
||||||
return DRM(addbufs_agp)( inode, filp, cmd, arg );
|
return DRM(addbufs_agp)( inode, filp, cmd, arg );
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
#if __HAVE_SG
|
||||||
|
if ( request.flags & _DRM_SG_BUFFER )
|
||||||
|
return DRM(addbufs_sg)( inode, filp, cmd, arg );
|
||||||
|
else
|
||||||
|
#endif
|
||||||
#if __HAVE_PCI_DMA
|
#if __HAVE_PCI_DMA
|
||||||
return DRM(addbufs_pci)( inode, filp, cmd, arg );
|
return DRM(addbufs_pci)( inode, filp, cmd, arg );
|
||||||
#else
|
#else
|
||||||
|
@ -760,7 +937,8 @@ int DRM(mapbufs)( struct inode *inode, struct file *filp,
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
if ( request.count >= dma->buf_count ) {
|
if ( request.count >= dma->buf_count ) {
|
||||||
if ( __HAVE_AGP && (dma->flags & _DRM_DMA_USE_AGP) ) {
|
if ( (__HAVE_AGP && (dma->flags & _DRM_DMA_USE_AGP)) ||
|
||||||
|
(__HAVE_SG && (dma->flags & _DRM_DMA_USE_SG)) ) {
|
||||||
drm_map_t *map = DRIVER_AGP_BUFFERS_MAP( dev );
|
drm_map_t *map = DRIVER_AGP_BUFFERS_MAP( dev );
|
||||||
|
|
||||||
if ( !map ) {
|
if ( !map ) {
|
||||||
|
|
|
@ -81,6 +81,9 @@
|
||||||
#ifndef __HAVE_COUNTERS
|
#ifndef __HAVE_COUNTERS
|
||||||
#define __HAVE_COUNTERS 0
|
#define __HAVE_COUNTERS 0
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef __HAVE_SG
|
||||||
|
#define __HAVE_SG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef DRIVER_PREINIT
|
#ifndef DRIVER_PREINIT
|
||||||
#define DRIVER_PREINIT()
|
#define DRIVER_PREINIT()
|
||||||
|
@ -178,6 +181,11 @@ static drm_ioctl_desc_t DRM(ioctls)[] = {
|
||||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { DRM(agp_unbind), 1, 1 },
|
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { DRM(agp_unbind), 1, 1 },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if __HAVE_SG
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { DRM(sg_alloc), 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { DRM(sg_free), 1, 1 },
|
||||||
|
#endif
|
||||||
|
|
||||||
DRIVER_IOCTLS
|
DRIVER_IOCTLS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -415,6 +423,12 @@ static int DRM(takedown)( drm_device_t *dev )
|
||||||
* handled in the AGP/GART driver.
|
* handled in the AGP/GART driver.
|
||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
|
case _DRM_SCATTER_GATHER:
|
||||||
|
if(dev->sg) {
|
||||||
|
DRM(sg_cleanup)(dev->sg);
|
||||||
|
dev->sg = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
|
DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,21 @@ int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
|
||||||
}
|
}
|
||||||
up(&dev->struct_sem);
|
up(&dev->struct_sem);
|
||||||
|
|
||||||
|
#ifdef __alpha__
|
||||||
|
/*
|
||||||
|
* Default the hose
|
||||||
|
*/
|
||||||
|
if (!dev->hose) {
|
||||||
|
struct pci_dev *pci_dev;
|
||||||
|
pci_dev = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
|
||||||
|
if (pci_dev) dev->hose = pci_dev->sysdata;
|
||||||
|
if (!dev->hose) {
|
||||||
|
struct pci_bus *b = pci_bus_b(pci_root_buses.next);
|
||||||
|
if (b) dev->hose = b->sysdata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,11 @@
|
||||||
#define __NO_VERSION__
|
#define __NO_VERSION__
|
||||||
#include "drmP.h"
|
#include "drmP.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
int DRM(flags) = DRM_FLAG_DEBUG;
|
||||||
|
#else
|
||||||
int DRM(flags) = 0;
|
int DRM(flags) = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* drm_parse_option parses a single option. See description for
|
/* drm_parse_option parses a single option. See description for
|
||||||
* drm_parse_options for details.
|
* drm_parse_options for details.
|
||||||
|
|
|
@ -95,6 +95,27 @@ int DRM(setunique)(struct inode *inode, struct file *filp,
|
||||||
DRM_MEM_DRIVER);
|
DRM_MEM_DRIVER);
|
||||||
sprintf(dev->devname, "%s@%s", dev->name, dev->unique);
|
sprintf(dev->devname, "%s@%s", dev->name, dev->unique);
|
||||||
|
|
||||||
|
#ifdef __alpha__
|
||||||
|
do {
|
||||||
|
struct pci_dev *pci_dev;
|
||||||
|
int b, d, f;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
for(p = dev->unique; p && *p && *p != ':'; p++);
|
||||||
|
if (!p || !*p) break;
|
||||||
|
b = (int)simple_strtoul(p+1, &p, 10);
|
||||||
|
if (*p != ':') break;
|
||||||
|
d = (int)simple_strtoul(p+1, &p, 10);
|
||||||
|
if (*p != ':') break;
|
||||||
|
f = (int)simple_strtoul(p+1, &p, 10);
|
||||||
|
if (*p) break;
|
||||||
|
|
||||||
|
pci_dev = pci_find_slot(b, PCI_DEVFN(d,f));
|
||||||
|
if (pci_dev)
|
||||||
|
dev->hose = pci_dev->sysdata;
|
||||||
|
} while(0);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,7 @@ static drm_mem_stats_t DRM(mem_stats)[] = {
|
||||||
[DRM_MEM_MAPPINGS] = { "mappings" },
|
[DRM_MEM_MAPPINGS] = { "mappings" },
|
||||||
[DRM_MEM_BUFLISTS] = { "buflists" },
|
[DRM_MEM_BUFLISTS] = { "buflists" },
|
||||||
[DRM_MEM_AGPLISTS] = { "agplist" },
|
[DRM_MEM_AGPLISTS] = { "agplist" },
|
||||||
|
[DRM_MEM_SGLISTS] = { "sglist" },
|
||||||
[DRM_MEM_TOTALAGP] = { "totalagp" },
|
[DRM_MEM_TOTALAGP] = { "totalagp" },
|
||||||
[DRM_MEM_BOUNDAGP] = { "boundagp" },
|
[DRM_MEM_BOUNDAGP] = { "boundagp" },
|
||||||
[DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
|
[DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
|
||||||
|
|
|
@ -0,0 +1,218 @@
|
||||||
|
/* drm_scatter.h -- IOCTLs to manage scatter/gather memory -*- linux-c -*-
|
||||||
|
* Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com
|
||||||
|
*
|
||||||
|
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||||
|
* 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
|
||||||
|
* 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:
|
||||||
|
* Gareth Hughes <gareth@valinux.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define __NO_VERSION__
|
||||||
|
#include <linux/config.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include "drmP.h"
|
||||||
|
|
||||||
|
#define DEBUG_SCATTER 0
|
||||||
|
|
||||||
|
void DRM(sg_cleanup)( drm_sg_mem_t *entry )
|
||||||
|
{
|
||||||
|
struct page *page;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for ( i = 0 ; i < entry->pages ; i++ ) {
|
||||||
|
page = entry->pagelist[i];
|
||||||
|
if ( page )
|
||||||
|
ClearPageReserved( page );
|
||||||
|
}
|
||||||
|
|
||||||
|
vfree( entry->virtual );
|
||||||
|
|
||||||
|
DRM(free)( entry->pagelist,
|
||||||
|
entry->pages * sizeof(*entry->pagelist),
|
||||||
|
DRM_MEM_PAGES );
|
||||||
|
DRM(free)( entry,
|
||||||
|
sizeof(*entry),
|
||||||
|
DRM_MEM_SGLISTS );
|
||||||
|
}
|
||||||
|
|
||||||
|
int DRM(sg_alloc)( struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg )
|
||||||
|
{
|
||||||
|
drm_file_t *priv = filp->private_data;
|
||||||
|
drm_device_t *dev = priv->dev;
|
||||||
|
drm_scatter_gather_t request;
|
||||||
|
drm_sg_mem_t *entry;
|
||||||
|
unsigned long pages, i, j;
|
||||||
|
pgd_t *pgd;
|
||||||
|
pmd_t *pmd;
|
||||||
|
pte_t *pte;
|
||||||
|
|
||||||
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
|
if ( dev->sg )
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if ( copy_from_user( &request,
|
||||||
|
(drm_scatter_gather_t *)arg,
|
||||||
|
sizeof(request) ) )
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
entry = DRM(alloc)( sizeof(*entry), DRM_MEM_SGLISTS );
|
||||||
|
if ( !entry )
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
memset( entry, 0, sizeof(*entry) );
|
||||||
|
|
||||||
|
pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||||
|
DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages );
|
||||||
|
|
||||||
|
entry->pages = pages;
|
||||||
|
entry->pagelist = DRM(alloc)( pages * sizeof(*entry->pagelist),
|
||||||
|
DRM_MEM_PAGES );
|
||||||
|
if ( !entry->pagelist ) {
|
||||||
|
DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS );
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->virtual = vmalloc_32( pages << PAGE_SHIFT );
|
||||||
|
if ( !entry->virtual ) {
|
||||||
|
DRM(free)( entry->pagelist,
|
||||||
|
entry->pages * sizeof(*entry->pagelist),
|
||||||
|
DRM_MEM_PAGES );
|
||||||
|
DRM(free)( entry,
|
||||||
|
sizeof(*entry),
|
||||||
|
DRM_MEM_SGLISTS );
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This also forces the mapping of COW pages, so our page list
|
||||||
|
* will be valid. Please don't remove it...
|
||||||
|
*/
|
||||||
|
memset( entry->virtual, 0, pages << PAGE_SHIFT );
|
||||||
|
|
||||||
|
entry->handle = (unsigned long)entry->virtual;
|
||||||
|
|
||||||
|
DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle );
|
||||||
|
DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual );
|
||||||
|
|
||||||
|
for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) {
|
||||||
|
pgd = pgd_offset_k( i );
|
||||||
|
if ( !pgd_present( *pgd ) )
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
pmd = pmd_offset( pgd, i );
|
||||||
|
if ( !pmd_present( *pmd ) )
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
pte = pte_offset( pmd, i );
|
||||||
|
if ( !pte_present( *pte ) )
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
entry->pagelist[j] = pte_page( *pte );
|
||||||
|
|
||||||
|
SetPageReserved( entry->pagelist[j] );
|
||||||
|
}
|
||||||
|
|
||||||
|
request.handle = entry->handle;
|
||||||
|
|
||||||
|
if ( copy_to_user( (drm_scatter_gather_t *)arg,
|
||||||
|
&request,
|
||||||
|
sizeof(request) ) ) {
|
||||||
|
DRM(sg_cleanup)( entry );
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->sg = entry;
|
||||||
|
|
||||||
|
#if DEBUG_SCATTER
|
||||||
|
/* Verify that each page points to its virtual address, and vice
|
||||||
|
* versa.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
for ( i = 0 ; i < pages ; i++ ) {
|
||||||
|
unsigned long *tmp;
|
||||||
|
|
||||||
|
tmp = (unsigned long *)entry->pagelist[i]->virtual;
|
||||||
|
for ( j = 0 ;
|
||||||
|
j < PAGE_SIZE / sizeof(unsigned long) ;
|
||||||
|
j++, tmp++ ) {
|
||||||
|
*tmp = 0xcafebabe;
|
||||||
|
}
|
||||||
|
tmp = (unsigned long *)((u8 *)entry->virtual +
|
||||||
|
(PAGE_SIZE * i));
|
||||||
|
for( j = 0 ;
|
||||||
|
j < PAGE_SIZE / sizeof(unsigned long) ;
|
||||||
|
j++, tmp++ ) {
|
||||||
|
if ( *tmp != 0xcafebabe && error == 0 ) {
|
||||||
|
error = 1;
|
||||||
|
DRM_ERROR( "Scatter allocation error, "
|
||||||
|
"pagelist does not match "
|
||||||
|
"virtual mapping\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmp = (unsigned long *)entry->pagelist[i]->virtual;
|
||||||
|
for(j = 0 ;
|
||||||
|
j < PAGE_SIZE / sizeof(unsigned long) ;
|
||||||
|
j++, tmp++) {
|
||||||
|
*tmp = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (error == 0)
|
||||||
|
DRM_ERROR( "Scatter allocation matches pagelist\n" );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
DRM(sg_cleanup)( entry );
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DRM(sg_free)( struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg )
|
||||||
|
{
|
||||||
|
drm_file_t *priv = filp->private_data;
|
||||||
|
drm_device_t *dev = priv->dev;
|
||||||
|
drm_scatter_gather_t request;
|
||||||
|
drm_sg_mem_t *entry;
|
||||||
|
|
||||||
|
if ( copy_from_user( &request,
|
||||||
|
(drm_scatter_gather_t *)arg,
|
||||||
|
sizeof(request) ) )
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
entry = dev->sg;
|
||||||
|
dev->sg = NULL;
|
||||||
|
|
||||||
|
if ( !entry || entry->handle != request.handle )
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
DRM_DEBUG( "sg free virtual = %p\n", entry->virtual );
|
||||||
|
|
||||||
|
DRM(sg_cleanup)( entry );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -50,6 +50,12 @@ struct vm_operations_struct drm_vm_dma_ops = {
|
||||||
close: DRM(vm_close),
|
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),
|
||||||
|
};
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < 0x020317
|
#if LINUX_VERSION_CODE < 0x020317
|
||||||
unsigned long DRM(vm_nopage)(struct vm_area_struct *vma,
|
unsigned long DRM(vm_nopage)(struct vm_area_struct *vma,
|
||||||
unsigned long address,
|
unsigned long address,
|
||||||
|
@ -93,7 +99,7 @@ struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
|
||||||
offset = address - vma->vm_start;
|
offset = address - vma->vm_start;
|
||||||
i = (unsigned long)map->handle + offset;
|
i = (unsigned long)map->handle + offset;
|
||||||
/* We have to walk page tables here because we need large SAREA's, and
|
/* We have to walk page tables here because we need large SAREA's, and
|
||||||
* they need to be virtually contigious in kernel space.
|
* they need to be virtually contiguous in kernel space.
|
||||||
*/
|
*/
|
||||||
pgd = pgd_offset_k( i );
|
pgd = pgd_offset_k( i );
|
||||||
if( !pgd_present( *pgd ) ) return NOPAGE_OOM;
|
if( !pgd_present( *pgd ) ) return NOPAGE_OOM;
|
||||||
|
@ -187,6 +193,7 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
|
||||||
vfree(map->handle);
|
vfree(map->handle);
|
||||||
break;
|
break;
|
||||||
case _DRM_AGP:
|
case _DRM_AGP:
|
||||||
|
case _DRM_SCATTER_GATHER:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
|
DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
|
||||||
|
@ -230,6 +237,48 @@ struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE < 0x020317
|
||||||
|
unsigned long DRM(vm_sg_nopage)(struct vm_area_struct *vma,
|
||||||
|
unsigned long address,
|
||||||
|
int write_access)
|
||||||
|
#else
|
||||||
|
/* Return type changed in 2.3.23 */
|
||||||
|
struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
|
||||||
|
unsigned long address,
|
||||||
|
int write_access)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if LINUX_VERSION_CODE >= 0x020300
|
||||||
|
drm_map_t *map = (drm_map_t *)vma->vm_private_data;
|
||||||
|
#else
|
||||||
|
drm_map_t *map = (drm_map_t *)vma->vm_pte;
|
||||||
|
#endif
|
||||||
|
drm_file_t *priv = vma->vm_file->private_data;
|
||||||
|
drm_device_t *dev = priv->dev;
|
||||||
|
drm_sg_mem_t *entry = dev->sg;
|
||||||
|
unsigned long offset;
|
||||||
|
unsigned long map_offset;
|
||||||
|
unsigned long page_offset;
|
||||||
|
struct page *page;
|
||||||
|
|
||||||
|
if (!entry) return NOPAGE_SIGBUS; /* Error */
|
||||||
|
if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
|
||||||
|
if (!entry->pagelist) return NOPAGE_OOM ; /* Nothing allocated */
|
||||||
|
|
||||||
|
|
||||||
|
offset = address - vma->vm_start;
|
||||||
|
map_offset = map->offset - dev->sg->handle;
|
||||||
|
page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT);
|
||||||
|
page = entry->pagelist[page_offset];
|
||||||
|
atomic_inc(&page->count); /* Dec. by kernel */
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE < 0x020317
|
||||||
|
return (unsigned long)virt_to_phys(page->virtual);
|
||||||
|
#else
|
||||||
|
return page;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void DRM(vm_open)(struct vm_area_struct *vma)
|
void DRM(vm_open)(struct vm_area_struct *vma)
|
||||||
{
|
{
|
||||||
drm_file_t *priv = vma->vm_file->private_data;
|
drm_file_t *priv = vma->vm_file->private_data;
|
||||||
|
@ -322,6 +371,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
|
||||||
drm_device_t *dev = priv->dev;
|
drm_device_t *dev = priv->dev;
|
||||||
drm_map_t *map = NULL;
|
drm_map_t *map = NULL;
|
||||||
drm_map_list_t *r_list;
|
drm_map_list_t *r_list;
|
||||||
|
unsigned long offset = 0;
|
||||||
struct list_head *list;
|
struct list_head *list;
|
||||||
|
|
||||||
DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
|
DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
|
||||||
|
@ -374,19 +424,26 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
|
||||||
}
|
}
|
||||||
#elif defined(__ia64__)
|
#elif defined(__ia64__)
|
||||||
if (map->type != _DRM_AGP)
|
if (map->type != _DRM_AGP)
|
||||||
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
|
vma->vm_page_prot =
|
||||||
|
pgprot_writecombine(vma->vm_page_prot);
|
||||||
|
#elif defined(__powerpc__)
|
||||||
|
pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE | _PAGE_GUARDED;
|
||||||
#endif
|
#endif
|
||||||
vma->vm_flags |= VM_IO; /* not in core dump */
|
vma->vm_flags |= VM_IO; /* not in core dump */
|
||||||
}
|
}
|
||||||
|
#ifdef __alpha__
|
||||||
|
offset = dev->hose->dense_mem_base -
|
||||||
|
dev->hose->mem_space->start;
|
||||||
|
#endif
|
||||||
if (remap_page_range(vma->vm_start,
|
if (remap_page_range(vma->vm_start,
|
||||||
VM_OFFSET(vma),
|
VM_OFFSET(vma) + offset,
|
||||||
vma->vm_end - vma->vm_start,
|
vma->vm_end - vma->vm_start,
|
||||||
vma->vm_page_prot))
|
vma->vm_page_prot))
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx,"
|
DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx,"
|
||||||
" offset = 0x%lx\n",
|
" offset = 0x%lx\n",
|
||||||
map->type,
|
map->type,
|
||||||
vma->vm_start, vma->vm_end, VM_OFFSET(vma));
|
vma->vm_start, vma->vm_end, VM_OFFSET(vma) + offset);
|
||||||
vma->vm_ops = &drm_vm_ops;
|
vma->vm_ops = &drm_vm_ops;
|
||||||
break;
|
break;
|
||||||
case _DRM_SHM:
|
case _DRM_SHM:
|
||||||
|
@ -400,6 +457,15 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
|
||||||
DRM_KERNEL advisory is supported. */
|
DRM_KERNEL advisory is supported. */
|
||||||
vma->vm_flags |= VM_LOCKED;
|
vma->vm_flags |= VM_LOCKED;
|
||||||
break;
|
break;
|
||||||
|
case _DRM_SCATTER_GATHER:
|
||||||
|
vma->vm_ops = &drm_vm_sg_ops;
|
||||||
|
#if LINUX_VERSION_CODE >= 0x020300
|
||||||
|
vma->vm_private_data = (void *)map;
|
||||||
|
#else
|
||||||
|
vma->vm_pte = (unsigned long)map;
|
||||||
|
#endif
|
||||||
|
vma->vm_flags |= VM_LOCKED;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL; /* This should never happen. */
|
return -EINVAL; /* This should never happen. */
|
||||||
}
|
}
|
||||||
|
|
|
@ -237,7 +237,7 @@ typedef struct drm_mga_init {
|
||||||
MGA_CLEANUP_DMA = 0x02
|
MGA_CLEANUP_DMA = 0x02
|
||||||
} func;
|
} func;
|
||||||
|
|
||||||
int sarea_priv_offset;
|
unsigned long sarea_priv_offset;
|
||||||
|
|
||||||
int chipset;
|
int chipset;
|
||||||
int sgram;
|
int sgram;
|
||||||
|
@ -254,12 +254,12 @@ typedef struct drm_mga_init {
|
||||||
unsigned int texture_offset[MGA_NR_TEX_HEAPS];
|
unsigned int texture_offset[MGA_NR_TEX_HEAPS];
|
||||||
unsigned int texture_size[MGA_NR_TEX_HEAPS];
|
unsigned int texture_size[MGA_NR_TEX_HEAPS];
|
||||||
|
|
||||||
unsigned int fb_offset;
|
unsigned long fb_offset;
|
||||||
unsigned int mmio_offset;
|
unsigned long mmio_offset;
|
||||||
unsigned int status_offset;
|
unsigned long status_offset;
|
||||||
unsigned int warp_offset;
|
unsigned long warp_offset;
|
||||||
unsigned int primary_offset;
|
unsigned long primary_offset;
|
||||||
unsigned int buffers_offset;
|
unsigned long buffers_offset;
|
||||||
} drm_mga_init_t;
|
} drm_mga_init_t;
|
||||||
|
|
||||||
typedef struct drm_mga_fullscreen {
|
typedef struct drm_mga_fullscreen {
|
||||||
|
|
|
@ -37,9 +37,11 @@
|
||||||
/* General customization:
|
/* General customization:
|
||||||
*/
|
*/
|
||||||
#define __HAVE_AGP 1
|
#define __HAVE_AGP 1
|
||||||
#define __MUST_HAVE_AGP 1
|
#define __MUST_HAVE_AGP 0
|
||||||
#define __HAVE_MTRR 1
|
#define __HAVE_MTRR 1
|
||||||
#define __HAVE_CTX_BITMAP 1
|
#define __HAVE_CTX_BITMAP 1
|
||||||
|
#define __HAVE_SG 1
|
||||||
|
#define __HAVE_PCI_DMA 1
|
||||||
|
|
||||||
/* Driver customization:
|
/* Driver customization:
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -178,6 +178,8 @@ static void r128_cce_load_microcode( drm_r128_private_t *dev_priv )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
r128_do_wait_for_idle( dev_priv );
|
r128_do_wait_for_idle( dev_priv );
|
||||||
|
|
||||||
R128_WRITE( R128_PM4_MICROCODE_ADDR, 0 );
|
R128_WRITE( R128_PM4_MICROCODE_ADDR, 0 );
|
||||||
|
@ -208,7 +210,7 @@ int r128_do_cce_idle( drm_r128_private_t *dev_priv )
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
|
for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
|
||||||
if ( *dev_priv->ring.head == dev_priv->ring.tail ) {
|
if ( GET_RING_HEAD( &dev_priv->ring ) == dev_priv->ring.tail ) {
|
||||||
int pm4stat = R128_READ( R128_PM4_STAT );
|
int pm4stat = R128_READ( R128_PM4_STAT );
|
||||||
if ( ( (pm4stat & R128_PM4_FIFOCNT_MASK) >=
|
if ( ( (pm4stat & R128_PM4_FIFOCNT_MASK) >=
|
||||||
dev_priv->cce_fifo_size ) &&
|
dev_priv->cce_fifo_size ) &&
|
||||||
|
@ -249,7 +251,7 @@ static void r128_do_cce_reset( drm_r128_private_t *dev_priv )
|
||||||
{
|
{
|
||||||
R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
|
R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
|
||||||
R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
|
R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
|
||||||
*dev_priv->ring.head = 0;
|
SET_RING_HEAD( &dev_priv->ring, 0 );
|
||||||
dev_priv->ring.tail = 0;
|
dev_priv->ring.tail = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,19 +314,43 @@ static void r128_cce_init_ring_buffer( drm_device_t *dev )
|
||||||
u32 ring_start;
|
u32 ring_start;
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
/* The manual (p. 2) says this address is in "VM space". This
|
/* The manual (p. 2) says this address is in "VM space". This
|
||||||
* means it's an offset from the start of AGP space.
|
* means it's an offset from the start of AGP space.
|
||||||
*/
|
*/
|
||||||
ring_start = dev_priv->cce_ring->offset - dev->agp->base;
|
#if __REALLY_HAVE_AGP
|
||||||
|
if ( !dev_priv->is_pci )
|
||||||
|
ring_start = dev_priv->cce_ring->offset - dev->agp->base;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
ring_start = dev_priv->cce_ring->offset - dev->sg->handle;
|
||||||
|
|
||||||
R128_WRITE( R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET );
|
R128_WRITE( R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET );
|
||||||
|
|
||||||
R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
|
R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
|
||||||
R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
|
R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
|
||||||
|
|
||||||
/* DL_RPTR_ADDR is a physical address in AGP space. */
|
/* DL_RPTR_ADDR is a physical address in AGP space. */
|
||||||
*dev_priv->ring.head = 0;
|
SET_RING_HEAD( &dev_priv->ring, 0 );
|
||||||
R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
|
|
||||||
dev_priv->ring_rptr->offset );
|
if ( !dev_priv->is_pci ) {
|
||||||
|
R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
|
||||||
|
dev_priv->ring_rptr->offset );
|
||||||
|
} else {
|
||||||
|
drm_sg_mem_t *entry = dev->sg;
|
||||||
|
unsigned long tmp_ofs, page_ofs;
|
||||||
|
|
||||||
|
tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
|
||||||
|
page_ofs = tmp_ofs >> PAGE_SHIFT;
|
||||||
|
|
||||||
|
R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
|
||||||
|
virt_to_bus(entry->pagelist[page_ofs]->virtual));
|
||||||
|
|
||||||
|
DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
|
||||||
|
virt_to_bus(entry->pagelist[page_ofs]->virtual),
|
||||||
|
entry->handle + tmp_ofs );
|
||||||
|
}
|
||||||
|
|
||||||
/* Set watermark control */
|
/* Set watermark control */
|
||||||
R128_WRITE( R128_PM4_BUFFER_WM_CNTL,
|
R128_WRITE( R128_PM4_BUFFER_WM_CNTL,
|
||||||
|
@ -346,6 +372,8 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
|
||||||
drm_r128_private_t *dev_priv;
|
drm_r128_private_t *dev_priv;
|
||||||
struct list_head *list;
|
struct list_head *list;
|
||||||
|
|
||||||
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
dev_priv = DRM(alloc)( sizeof(drm_r128_private_t), DRM_MEM_DRIVER );
|
dev_priv = DRM(alloc)( sizeof(drm_r128_private_t), DRM_MEM_DRIVER );
|
||||||
if ( dev_priv == NULL )
|
if ( dev_priv == NULL )
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -355,11 +383,9 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
|
||||||
|
|
||||||
dev_priv->is_pci = init->is_pci;
|
dev_priv->is_pci = init->is_pci;
|
||||||
|
|
||||||
/* GH: We don't support PCI cards until PCI GART is implemented.
|
if ( dev_priv->is_pci && !dev->sg ) {
|
||||||
* Fail here so we can remove all checks for PCI cards around
|
DRM_DEBUG( "PCI GART memory not allocated!\n" );
|
||||||
* the CCE ring code.
|
DRM_ERROR( "PCI GART memory not allocated!\n" );
|
||||||
*/
|
|
||||||
if ( dev_priv->is_pci ) {
|
|
||||||
DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
|
DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
|
||||||
dev->dev_private = NULL;
|
dev->dev_private = NULL;
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -368,6 +394,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
|
||||||
dev_priv->usec_timeout = init->usec_timeout;
|
dev_priv->usec_timeout = init->usec_timeout;
|
||||||
if ( dev_priv->usec_timeout < 1 ||
|
if ( dev_priv->usec_timeout < 1 ||
|
||||||
dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT ) {
|
dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT ) {
|
||||||
|
DRM_DEBUG( "TIMEOUT problem!\n" );
|
||||||
DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
|
DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
|
||||||
dev->dev_private = NULL;
|
dev->dev_private = NULL;
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -387,6 +414,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
|
||||||
( init->cce_mode != R128_PM4_128BM_64INDBM ) &&
|
( init->cce_mode != R128_PM4_128BM_64INDBM ) &&
|
||||||
( init->cce_mode != R128_PM4_64BM_128INDBM ) &&
|
( init->cce_mode != R128_PM4_64BM_128INDBM ) &&
|
||||||
( init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM ) ) {
|
( init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM ) ) {
|
||||||
|
DRM_DEBUG( "Bad cce_mode!\n" );
|
||||||
DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
|
DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
|
||||||
dev->dev_private = NULL;
|
dev->dev_private = NULL;
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -476,9 +504,24 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
|
||||||
(drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
|
(drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
|
||||||
init->sarea_priv_offset);
|
init->sarea_priv_offset);
|
||||||
|
|
||||||
DRM_IOREMAP( dev_priv->cce_ring );
|
if ( !dev_priv->is_pci ) {
|
||||||
DRM_IOREMAP( dev_priv->ring_rptr );
|
DRM_IOREMAP( dev_priv->cce_ring );
|
||||||
DRM_IOREMAP( dev_priv->buffers );
|
DRM_IOREMAP( dev_priv->ring_rptr );
|
||||||
|
DRM_IOREMAP( dev_priv->buffers );
|
||||||
|
} else {
|
||||||
|
dev_priv->cce_ring->handle =
|
||||||
|
(void *)dev_priv->cce_ring->offset;
|
||||||
|
dev_priv->ring_rptr->handle =
|
||||||
|
(void *)dev_priv->ring_rptr->offset;
|
||||||
|
dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __REALLY_HAVE_AGP
|
||||||
|
if ( !dev_priv->is_pci )
|
||||||
|
dev_priv->cce_buffers_offset = dev->agp->base;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
dev_priv->cce_buffers_offset = dev->sg->handle;
|
||||||
|
|
||||||
dev_priv->ring.head = ((__volatile__ u32 *)
|
dev_priv->ring.head = ((__volatile__ u32 *)
|
||||||
dev_priv->ring_rptr->handle);
|
dev_priv->ring_rptr->handle);
|
||||||
|
@ -501,6 +544,20 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
|
||||||
R128_WRITE( R128_LAST_DISPATCH_REG,
|
R128_WRITE( R128_LAST_DISPATCH_REG,
|
||||||
dev_priv->sarea_priv->last_dispatch );
|
dev_priv->sarea_priv->last_dispatch );
|
||||||
|
|
||||||
|
if ( dev_priv->is_pci ) {
|
||||||
|
dev_priv->phys_pci_gart = DRM(ati_pcigart_init)( dev );
|
||||||
|
if ( !dev_priv->phys_pci_gart ) {
|
||||||
|
DRM_DEBUG( "failed to init PCI GART!\n" );
|
||||||
|
DRM_ERROR( "failed to init PCI GART!\n" );
|
||||||
|
DRM(free)( dev_priv, sizeof(*dev_priv),
|
||||||
|
DRM_MEM_DRIVER );
|
||||||
|
dev->dev_private = NULL;
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
R128_WRITE( R128_PCI_GART_PAGE,
|
||||||
|
virt_to_bus( (void *)dev_priv->phys_pci_gart ) );
|
||||||
|
}
|
||||||
|
|
||||||
r128_cce_init_ring_buffer( dev );
|
r128_cce_init_ring_buffer( dev );
|
||||||
r128_cce_load_microcode( dev_priv );
|
r128_cce_load_microcode( dev_priv );
|
||||||
r128_do_engine_reset( dev );
|
r128_do_engine_reset( dev );
|
||||||
|
@ -513,9 +570,11 @@ int r128_do_cleanup_cce( drm_device_t *dev )
|
||||||
if ( dev->dev_private ) {
|
if ( dev->dev_private ) {
|
||||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||||
|
|
||||||
DRM_IOREMAPFREE( dev_priv->cce_ring );
|
if ( !dev_priv->is_pci ) {
|
||||||
DRM_IOREMAPFREE( dev_priv->ring_rptr );
|
DRM_IOREMAPFREE( dev_priv->cce_ring );
|
||||||
DRM_IOREMAPFREE( dev_priv->buffers );
|
DRM_IOREMAPFREE( dev_priv->ring_rptr );
|
||||||
|
DRM_IOREMAPFREE( dev_priv->buffers );
|
||||||
|
}
|
||||||
|
|
||||||
DRM(free)( dev->dev_private, sizeof(drm_r128_private_t),
|
DRM(free)( dev->dev_private, sizeof(drm_r128_private_t),
|
||||||
DRM_MEM_DRIVER );
|
DRM_MEM_DRIVER );
|
||||||
|
@ -532,6 +591,8 @@ int r128_cce_init( struct inode *inode, struct file *filp,
|
||||||
drm_device_t *dev = priv->dev;
|
drm_device_t *dev = priv->dev;
|
||||||
drm_r128_init_t init;
|
drm_r128_init_t init;
|
||||||
|
|
||||||
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
if ( copy_from_user( &init, (drm_r128_init_t *)arg, sizeof(init) ) )
|
if ( copy_from_user( &init, (drm_r128_init_t *)arg, sizeof(init) ) )
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
|
|
|
@ -175,7 +175,7 @@ typedef struct drm_r128_init {
|
||||||
R128_INIT_CCE = 0x01,
|
R128_INIT_CCE = 0x01,
|
||||||
R128_CLEANUP_CCE = 0x02
|
R128_CLEANUP_CCE = 0x02
|
||||||
} func;
|
} func;
|
||||||
int sarea_priv_offset;
|
unsigned long sarea_priv_offset;
|
||||||
int is_pci;
|
int is_pci;
|
||||||
int cce_mode;
|
int cce_mode;
|
||||||
int cce_secure;
|
int cce_secure;
|
||||||
|
@ -189,12 +189,12 @@ typedef struct drm_r128_init {
|
||||||
unsigned int depth_offset, depth_pitch;
|
unsigned int depth_offset, depth_pitch;
|
||||||
unsigned int span_offset;
|
unsigned int span_offset;
|
||||||
|
|
||||||
unsigned int fb_offset;
|
unsigned long fb_offset;
|
||||||
unsigned int mmio_offset;
|
unsigned long mmio_offset;
|
||||||
unsigned int ring_offset;
|
unsigned long ring_offset;
|
||||||
unsigned int ring_rptr_offset;
|
unsigned long ring_rptr_offset;
|
||||||
unsigned int buffers_offset;
|
unsigned long buffers_offset;
|
||||||
unsigned int agp_textures_offset;
|
unsigned long agp_textures_offset;
|
||||||
} drm_r128_init_t;
|
} drm_r128_init_t;
|
||||||
|
|
||||||
typedef struct drm_r128_cce_stop {
|
typedef struct drm_r128_cce_stop {
|
||||||
|
|
|
@ -33,16 +33,17 @@
|
||||||
#include "r128.h"
|
#include "r128.h"
|
||||||
#include "drmP.h"
|
#include "drmP.h"
|
||||||
#include "r128_drv.h"
|
#include "r128_drv.h"
|
||||||
|
#include "ati_pcigart.h"
|
||||||
|
|
||||||
#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc."
|
#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc."
|
||||||
|
|
||||||
#define DRIVER_NAME "r128"
|
#define DRIVER_NAME "r128"
|
||||||
#define DRIVER_DESC "ATI Rage 128"
|
#define DRIVER_DESC "ATI Rage 128"
|
||||||
#define DRIVER_DATE "20010308"
|
#define DRIVER_DATE "20010405"
|
||||||
|
|
||||||
#define DRIVER_MAJOR 2
|
#define DRIVER_MAJOR 2
|
||||||
#define DRIVER_MINOR 1
|
#define DRIVER_MINOR 1
|
||||||
#define DRIVER_PATCHLEVEL 5
|
#define DRIVER_PATCHLEVEL 6
|
||||||
|
|
||||||
#define DRIVER_IOCTLS \
|
#define DRIVER_IOCTLS \
|
||||||
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { r128_cce_buffers, 1, 0 }, \
|
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { r128_cce_buffers, 1, 0 }, \
|
||||||
|
@ -88,3 +89,4 @@
|
||||||
#include "drm_proc.h"
|
#include "drm_proc.h"
|
||||||
#include "drm_vm.h"
|
#include "drm_vm.h"
|
||||||
#include "drm_stub.h"
|
#include "drm_stub.h"
|
||||||
|
#include "drm_scatter.h"
|
||||||
|
|
|
@ -28,11 +28,15 @@
|
||||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||||
* Kevin E. Martin <martin@valinux.com>
|
* Kevin E. Martin <martin@valinux.com>
|
||||||
* Gareth Hughes <gareth@valinux.com>
|
* Gareth Hughes <gareth@valinux.com>
|
||||||
|
* Michel Dänzer <daenzerm@student.ethz.ch>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __R128_DRV_H__
|
#ifndef __R128_DRV_H__
|
||||||
#define __R128_DRV_H__
|
#define __R128_DRV_H__
|
||||||
|
|
||||||
|
#define GET_RING_HEAD( ring ) le32_to_cpu( *(ring)->head )
|
||||||
|
#define SET_RING_HEAD( ring, val ) *(ring)->head = cpu_to_le32( val )
|
||||||
|
|
||||||
typedef struct drm_r128_freelist {
|
typedef struct drm_r128_freelist {
|
||||||
unsigned int age;
|
unsigned int age;
|
||||||
drm_buf_t *buf;
|
drm_buf_t *buf;
|
||||||
|
@ -67,6 +71,8 @@ typedef struct drm_r128_private {
|
||||||
|
|
||||||
int usec_timeout;
|
int usec_timeout;
|
||||||
int is_pci;
|
int is_pci;
|
||||||
|
unsigned long phys_pci_gart;
|
||||||
|
unsigned long cce_buffers_offset;
|
||||||
|
|
||||||
atomic_t idle_count;
|
atomic_t idle_count;
|
||||||
|
|
||||||
|
@ -134,7 +140,7 @@ extern int r128_wait_ring( drm_r128_private_t *dev_priv, int n );
|
||||||
static inline void
|
static inline void
|
||||||
r128_update_ring_snapshot( drm_r128_ring_buffer_t *ring )
|
r128_update_ring_snapshot( drm_r128_ring_buffer_t *ring )
|
||||||
{
|
{
|
||||||
ring->space = (*(volatile int *)ring->head - ring->tail) * sizeof(u32);
|
ring->space = (GET_RING_HEAD( ring ) - ring->tail) * sizeof(u32);
|
||||||
if ( ring->space <= 0 )
|
if ( ring->space <= 0 )
|
||||||
ring->space += ring->size;
|
ring->space += ring->size;
|
||||||
}
|
}
|
||||||
|
@ -248,6 +254,7 @@ extern int r128_cce_indirect( struct inode *inode, struct file *filp,
|
||||||
# define R128_PC_FLUSH_ALL 0x00ff
|
# define R128_PC_FLUSH_ALL 0x00ff
|
||||||
# define R128_PC_BUSY (1 << 31)
|
# define R128_PC_BUSY (1 << 31)
|
||||||
|
|
||||||
|
#define R128_PCI_GART_PAGE 0x017c
|
||||||
#define R128_PRIM_TEX_CNTL_C 0x1cb0
|
#define R128_PRIM_TEX_CNTL_C 0x1cb0
|
||||||
|
|
||||||
#define R128_SCALE_3D_CNTL 0x1a00
|
#define R128_SCALE_3D_CNTL 0x1a00
|
||||||
|
@ -365,7 +372,7 @@ extern int r128_cce_indirect( struct inode *inode, struct file *filp,
|
||||||
|
|
||||||
#define R128_LAST_FRAME_REG R128_GUI_SCRATCH_REG0
|
#define R128_LAST_FRAME_REG R128_GUI_SCRATCH_REG0
|
||||||
#define R128_LAST_DISPATCH_REG R128_GUI_SCRATCH_REG1
|
#define R128_LAST_DISPATCH_REG R128_GUI_SCRATCH_REG1
|
||||||
#define R128_MAX_VB_AGE 0xffffffff
|
#define R128_MAX_VB_AGE 0x7fffffff
|
||||||
#define R128_MAX_VB_VERTS (0xffff)
|
#define R128_MAX_VB_VERTS (0xffff)
|
||||||
|
|
||||||
#define R128_RING_HIGH_MARK 128
|
#define R128_RING_HIGH_MARK 128
|
||||||
|
@ -373,17 +380,36 @@ extern int r128_cce_indirect( struct inode *inode, struct file *filp,
|
||||||
#define R128_PERFORMANCE_BOXES 0
|
#define R128_PERFORMANCE_BOXES 0
|
||||||
|
|
||||||
|
|
||||||
#define R128_BASE(reg) ((u32)(dev_priv->mmio->handle))
|
#define R128_BASE(reg) ((unsigned long)(dev_priv->mmio->handle))
|
||||||
#define R128_ADDR(reg) (R128_BASE( reg ) + reg)
|
#define R128_ADDR(reg) (R128_BASE( reg ) + reg)
|
||||||
|
|
||||||
#define R128_DEREF(reg) *(volatile u32 *)R128_ADDR( reg )
|
#define R128_DEREF(reg) *(volatile u32 *)R128_ADDR( reg )
|
||||||
#define R128_READ(reg) R128_DEREF( reg )
|
#ifdef __alpha__
|
||||||
#define R128_WRITE(reg,val) do { R128_DEREF( reg ) = val; } while (0)
|
#define R128_READ(reg) (_R128_READ((u32 *)R128_ADDR(reg)))
|
||||||
|
static inline u32 _R128_READ(u32 *addr) {
|
||||||
|
mb();
|
||||||
|
return *(volatile u32 *)addr;
|
||||||
|
}
|
||||||
|
#define R128_WRITE(reg,val) \
|
||||||
|
do { wmb(); R128_DEREF(reg) = val; } while (0)
|
||||||
|
#else
|
||||||
|
#define R128_READ(reg) le32_to_cpu( R128_DEREF( reg ) )
|
||||||
|
#define R128_WRITE(reg,val) do { R128_DEREF( reg ) = cpu_to_le32( val ); } while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define R128_DEREF8(reg) *(volatile u8 *)R128_ADDR( reg )
|
#define R128_DEREF8(reg) *(volatile u8 *)R128_ADDR( reg )
|
||||||
|
#ifdef __alpha__
|
||||||
|
#define R128_READ8(reg) _R128_READ8((u8 *)R128_ADDR(reg))
|
||||||
|
static inline u8 _R128_READ8(u8 *addr) {
|
||||||
|
mb();
|
||||||
|
return *(volatile u8 *)addr;
|
||||||
|
}
|
||||||
|
#define R128_WRITE8(reg,val) \
|
||||||
|
do { wmb(); R128_DEREF8(reg) = val; } while (0)
|
||||||
|
#else
|
||||||
#define R128_READ8(reg) R128_DEREF8( reg )
|
#define R128_READ8(reg) R128_DEREF8( reg )
|
||||||
#define R128_WRITE8(reg,val) do { R128_DEREF8( reg ) = val; } while (0)
|
#define R128_WRITE8(reg,val) do { R128_DEREF8( reg ) = val; } while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define R128_WRITE_PLL(addr,val) \
|
#define R128_WRITE_PLL(addr,val) \
|
||||||
do { \
|
do { \
|
||||||
|
@ -485,7 +511,7 @@ do { \
|
||||||
|
|
||||||
#define ADVANCE_RING() do { \
|
#define ADVANCE_RING() do { \
|
||||||
if ( R128_VERBOSE ) { \
|
if ( R128_VERBOSE ) { \
|
||||||
DRM_INFO( "ADVANCE_RING() tail=0x%06x wr=0x%06x\n", \
|
DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \
|
||||||
write, dev_priv->ring.tail ); \
|
write, dev_priv->ring.tail ); \
|
||||||
} \
|
} \
|
||||||
if ( R128_BROKEN_CCE && write < 32 ) { \
|
if ( R128_BROKEN_CCE && write < 32 ) { \
|
||||||
|
@ -503,7 +529,7 @@ do { \
|
||||||
DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \
|
DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \
|
||||||
(unsigned int)(x), write ); \
|
(unsigned int)(x), write ); \
|
||||||
} \
|
} \
|
||||||
ring[write++] = (x); \
|
ring[write++] = cpu_to_le32( x ); \
|
||||||
write &= tail_mask; \
|
write &= tail_mask; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
|
@ -660,7 +660,7 @@ static void r128_cce_dispatch_indirect( drm_device_t *dev,
|
||||||
u32 *data = (u32 *)
|
u32 *data = (u32 *)
|
||||||
((char *)dev_priv->buffers->handle
|
((char *)dev_priv->buffers->handle
|
||||||
+ buf->offset + start);
|
+ buf->offset + start);
|
||||||
data[dwords++] = R128_CCE_PACKET2;
|
data[dwords++] = cpu_to_le32( R128_CCE_PACKET2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
buf_priv->dispatched = 1;
|
buf_priv->dispatched = 1;
|
||||||
|
@ -704,7 +704,7 @@ static void r128_cce_dispatch_indices( drm_device_t *dev,
|
||||||
drm_r128_buf_priv_t *buf_priv = buf->dev_private;
|
drm_r128_buf_priv_t *buf_priv = buf->dev_private;
|
||||||
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||||
int format = sarea_priv->vc_format;
|
int format = sarea_priv->vc_format;
|
||||||
int offset = dev_priv->buffers->offset - dev->agp->base;
|
int offset = dev_priv->buffers->offset - dev_priv->cce_buffers_offset;
|
||||||
int prim = buf_priv->prim;
|
int prim = buf_priv->prim;
|
||||||
u32 *data;
|
u32 *data;
|
||||||
int dwords;
|
int dwords;
|
||||||
|
@ -727,16 +727,21 @@ static void r128_cce_dispatch_indices( drm_device_t *dev,
|
||||||
data = (u32 *)((char *)dev_priv->buffers->handle
|
data = (u32 *)((char *)dev_priv->buffers->handle
|
||||||
+ buf->offset + start);
|
+ buf->offset + start);
|
||||||
|
|
||||||
data[0] = CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM, dwords-2 );
|
data[0] = cpu_to_le32( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM,
|
||||||
|
dwords-2 ) );
|
||||||
|
|
||||||
data[1] = offset;
|
data[1] = cpu_to_le32( offset );
|
||||||
data[2] = R128_MAX_VB_VERTS;
|
data[2] = cpu_to_le32( R128_MAX_VB_VERTS );
|
||||||
data[3] = format;
|
data[3] = cpu_to_le32( format );
|
||||||
data[4] = (prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
|
data[4] = cpu_to_le32( (prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
|
||||||
(count << 16));
|
(count << 16)) );
|
||||||
|
|
||||||
if ( count & 0x1 ) {
|
if ( count & 0x1 ) {
|
||||||
|
#ifdef __LITTLE_ENDIAN
|
||||||
data[dwords-1] &= 0x0000ffff;
|
data[dwords-1] &= 0x0000ffff;
|
||||||
|
#else
|
||||||
|
data[dwords-1] &= 0xffff0000;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -842,23 +847,23 @@ static int r128_cce_dispatch_blit( drm_device_t *dev,
|
||||||
|
|
||||||
data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
|
data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
|
||||||
|
|
||||||
data[0] = CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 );
|
data[0] = cpu_to_le32( CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 ) );
|
||||||
data[1] = (R128_GMC_DST_PITCH_OFFSET_CNTL |
|
data[1] = cpu_to_le32( (R128_GMC_DST_PITCH_OFFSET_CNTL |
|
||||||
R128_GMC_BRUSH_NONE |
|
R128_GMC_BRUSH_NONE |
|
||||||
(blit->format << 8) |
|
(blit->format << 8) |
|
||||||
R128_GMC_SRC_DATATYPE_COLOR |
|
R128_GMC_SRC_DATATYPE_COLOR |
|
||||||
R128_ROP3_S |
|
R128_ROP3_S |
|
||||||
R128_DP_SRC_SOURCE_HOST_DATA |
|
R128_DP_SRC_SOURCE_HOST_DATA |
|
||||||
R128_GMC_CLR_CMP_CNTL_DIS |
|
R128_GMC_CLR_CMP_CNTL_DIS |
|
||||||
R128_GMC_AUX_CLIP_DIS |
|
R128_GMC_AUX_CLIP_DIS |
|
||||||
R128_GMC_WR_MSK_DIS);
|
R128_GMC_WR_MSK_DIS) );
|
||||||
|
|
||||||
data[2] = (blit->pitch << 21) | (blit->offset >> 5);
|
data[2] = cpu_to_le32( (blit->pitch << 21) | (blit->offset >> 5) );
|
||||||
data[3] = 0xffffffff;
|
data[3] = cpu_to_le32( 0xffffffff );
|
||||||
data[4] = 0xffffffff;
|
data[4] = cpu_to_le32( 0xffffffff );
|
||||||
data[5] = (blit->y << 16) | blit->x;
|
data[5] = cpu_to_le32( (blit->y << 16) | blit->x );
|
||||||
data[6] = (blit->height << 16) | blit->width;
|
data[6] = cpu_to_le32( (blit->height << 16) | blit->width );
|
||||||
data[7] = dwords;
|
data[7] = cpu_to_le32( dwords );
|
||||||
|
|
||||||
buf->used = (dwords + 8) * sizeof(u32);
|
buf->used = (dwords + 8) * sizeof(u32);
|
||||||
|
|
||||||
|
@ -1299,8 +1304,8 @@ int r128_cce_vertex( struct inode *inode, struct file *filp,
|
||||||
|
|
||||||
LOCK_TEST_WITH_RETURN( dev );
|
LOCK_TEST_WITH_RETURN( dev );
|
||||||
|
|
||||||
if ( !dev_priv || dev_priv->is_pci ) {
|
if ( !dev_priv ) {
|
||||||
DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
|
DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1362,8 +1367,8 @@ int r128_cce_indices( struct inode *inode, struct file *filp,
|
||||||
|
|
||||||
LOCK_TEST_WITH_RETURN( dev );
|
LOCK_TEST_WITH_RETURN( dev );
|
||||||
|
|
||||||
if ( !dev_priv || dev_priv->is_pci ) {
|
if ( !dev_priv ) {
|
||||||
DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
|
DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,11 @@
|
||||||
/* General customization:
|
/* General customization:
|
||||||
*/
|
*/
|
||||||
#define __HAVE_AGP 1
|
#define __HAVE_AGP 1
|
||||||
#define __MUST_HAVE_AGP 1
|
#define __MUST_HAVE_AGP 0
|
||||||
#define __HAVE_MTRR 1
|
#define __HAVE_MTRR 1
|
||||||
#define __HAVE_CTX_BITMAP 1
|
#define __HAVE_CTX_BITMAP 1
|
||||||
|
#define __HAVE_SG 1
|
||||||
|
#define __HAVE_PCI_DMA 1
|
||||||
|
|
||||||
/* Driver customization:
|
/* Driver customization:
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -24,12 +24,12 @@
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Kevin E. Martin <martin@valinux.com>
|
* Kevin E. Martin <martin@valinux.com>
|
||||||
* Gareth Hughes <gareth@valinux.com>
|
* Gareth Hughes <gareth@valinux.com>
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define __NO_VERSION__
|
#define __NO_VERSION__
|
||||||
|
#include "radeon.h"
|
||||||
#include "drmP.h"
|
#include "drmP.h"
|
||||||
#include "radeon_drv.h"
|
#include "radeon_drv.h"
|
||||||
|
|
||||||
|
@ -300,26 +300,6 @@ static u32 radeon_cp_microcode[][2] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#define DO_IOREMAP(_m) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size)
|
|
||||||
|
|
||||||
#define DO_IOREMAPFREE(_m) \
|
|
||||||
do { \
|
|
||||||
if ((_m)->handle && (_m)->size) \
|
|
||||||
drm_ioremapfree((_m)->handle, (_m)->size); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define DO_FIND_MAP(_m, _o) \
|
|
||||||
do { \
|
|
||||||
int _i; \
|
|
||||||
for (_i = 0; _i < dev->map_count; _i++) { \
|
|
||||||
if (dev->maplist[_i]->offset == _o) { \
|
|
||||||
_m = dev->maplist[_i]; \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
|
|
||||||
int RADEON_READ_PLL(drm_device_t *dev, int addr)
|
int RADEON_READ_PLL(drm_device_t *dev, int addr)
|
||||||
{
|
{
|
||||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||||
|
@ -338,6 +318,16 @@ static void radeon_status( drm_radeon_private_t *dev_priv )
|
||||||
(unsigned int)RADEON_READ( RADEON_CP_RB_RPTR ) );
|
(unsigned int)RADEON_READ( RADEON_CP_RB_RPTR ) );
|
||||||
printk( "CP_RB_WTPR = 0x%08x\n",
|
printk( "CP_RB_WTPR = 0x%08x\n",
|
||||||
(unsigned int)RADEON_READ( RADEON_CP_RB_WPTR ) );
|
(unsigned int)RADEON_READ( RADEON_CP_RB_WPTR ) );
|
||||||
|
printk( "AIC_CNTL = 0x%08x\n",
|
||||||
|
(unsigned int)RADEON_READ( RADEON_AIC_CNTL ) );
|
||||||
|
printk( "AIC_STAT = 0x%08x\n",
|
||||||
|
(unsigned int)RADEON_READ( RADEON_AIC_STAT ) );
|
||||||
|
printk( "AIC_PT_BASE = 0x%08x\n",
|
||||||
|
(unsigned int)RADEON_READ( RADEON_AIC_PT_BASE ) );
|
||||||
|
printk( "TLB_ADDR = 0x%08x\n",
|
||||||
|
(unsigned int)RADEON_READ( RADEON_AIC_TLB_ADDR ) );
|
||||||
|
printk( "TLB_DATA = 0x%08x\n",
|
||||||
|
(unsigned int)RADEON_READ( RADEON_AIC_TLB_DATA ) );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -421,6 +411,7 @@ static int radeon_do_wait_for_idle( drm_radeon_private_t *dev_priv )
|
||||||
static void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv )
|
static void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
radeon_do_wait_for_idle( dev_priv );
|
radeon_do_wait_for_idle( dev_priv );
|
||||||
|
|
||||||
|
@ -439,6 +430,7 @@ static void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv )
|
||||||
*/
|
*/
|
||||||
static void radeon_do_cp_flush( drm_radeon_private_t *dev_priv )
|
static void radeon_do_cp_flush( drm_radeon_private_t *dev_priv )
|
||||||
{
|
{
|
||||||
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
#if 0
|
#if 0
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
|
@ -452,6 +444,7 @@ static void radeon_do_cp_flush( drm_radeon_private_t *dev_priv )
|
||||||
int radeon_do_cp_idle( drm_radeon_private_t *dev_priv )
|
int radeon_do_cp_idle( drm_radeon_private_t *dev_priv )
|
||||||
{
|
{
|
||||||
RING_LOCALS;
|
RING_LOCALS;
|
||||||
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
BEGIN_RING( 6 );
|
BEGIN_RING( 6 );
|
||||||
|
|
||||||
|
@ -469,6 +462,7 @@ int radeon_do_cp_idle( drm_radeon_private_t *dev_priv )
|
||||||
static void radeon_do_cp_start( drm_radeon_private_t *dev_priv )
|
static void radeon_do_cp_start( drm_radeon_private_t *dev_priv )
|
||||||
{
|
{
|
||||||
RING_LOCALS;
|
RING_LOCALS;
|
||||||
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
radeon_do_wait_for_idle( dev_priv );
|
radeon_do_wait_for_idle( dev_priv );
|
||||||
|
|
||||||
|
@ -492,6 +486,7 @@ static void radeon_do_cp_start( drm_radeon_private_t *dev_priv )
|
||||||
static void radeon_do_cp_reset( drm_radeon_private_t *dev_priv )
|
static void radeon_do_cp_reset( drm_radeon_private_t *dev_priv )
|
||||||
{
|
{
|
||||||
u32 cur_read_ptr;
|
u32 cur_read_ptr;
|
||||||
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
|
cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
|
||||||
RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
|
RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
|
||||||
|
@ -505,6 +500,8 @@ static void radeon_do_cp_reset( drm_radeon_private_t *dev_priv )
|
||||||
*/
|
*/
|
||||||
static void radeon_do_cp_stop( drm_radeon_private_t *dev_priv )
|
static void radeon_do_cp_stop( drm_radeon_private_t *dev_priv )
|
||||||
{
|
{
|
||||||
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
RADEON_WRITE( RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS );
|
RADEON_WRITE( RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS );
|
||||||
|
|
||||||
dev_priv->cp_running = 0;
|
dev_priv->cp_running = 0;
|
||||||
|
@ -571,18 +568,29 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev )
|
||||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||||
u32 ring_start, cur_read_ptr;
|
u32 ring_start, cur_read_ptr;
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
/* Initialize the memory controller */
|
/* Initialize the memory controller */
|
||||||
RADEON_WRITE( RADEON_MC_FB_LOCATION,
|
RADEON_WRITE( RADEON_MC_FB_LOCATION,
|
||||||
(dev_priv->agp_vm_start - 1) & 0xffff0000 );
|
(dev_priv->agp_vm_start - 1) & 0xffff0000 );
|
||||||
RADEON_WRITE( RADEON_MC_AGP_LOCATION,
|
|
||||||
(((dev_priv->agp_vm_start - 1 +
|
|
||||||
dev_priv->agp_size) & 0xffff0000) |
|
|
||||||
(dev_priv->agp_vm_start >> 16)) );
|
|
||||||
|
|
||||||
ring_start = (dev_priv->cp_ring->offset
|
if ( !dev_priv->is_pci ) {
|
||||||
- dev->agp->base
|
RADEON_WRITE( RADEON_MC_AGP_LOCATION,
|
||||||
+ dev_priv->agp_vm_start);
|
(((dev_priv->agp_vm_start - 1 +
|
||||||
|
dev_priv->agp_size) & 0xffff0000) |
|
||||||
|
(dev_priv->agp_vm_start >> 16)) );
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __REALLY_HAVE_AGP
|
||||||
|
if ( !dev_priv->is_pci )
|
||||||
|
ring_start = (dev_priv->cp_ring->offset
|
||||||
|
- dev->agp->base
|
||||||
|
+ dev_priv->agp_vm_start);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
ring_start = (dev_priv->cp_ring->offset
|
||||||
|
- dev->sg->handle
|
||||||
|
+ dev_priv->agp_vm_start);
|
||||||
|
|
||||||
RADEON_WRITE( RADEON_CP_RB_BASE, ring_start );
|
RADEON_WRITE( RADEON_CP_RB_BASE, ring_start );
|
||||||
|
|
||||||
|
@ -595,17 +603,29 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev )
|
||||||
*dev_priv->ring.head = cur_read_ptr;
|
*dev_priv->ring.head = cur_read_ptr;
|
||||||
dev_priv->ring.tail = cur_read_ptr;
|
dev_priv->ring.tail = cur_read_ptr;
|
||||||
|
|
||||||
RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, dev_priv->ring_rptr->offset );
|
if ( !dev_priv->is_pci ) {
|
||||||
|
RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
|
||||||
|
dev_priv->ring_rptr->offset );
|
||||||
|
} else {
|
||||||
|
drm_sg_mem_t *entry = dev->sg;
|
||||||
|
unsigned long tmp_ofs, page_ofs;
|
||||||
|
|
||||||
|
tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
|
||||||
|
page_ofs = tmp_ofs >> PAGE_SHIFT;
|
||||||
|
|
||||||
|
RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
|
||||||
|
virt_to_bus(entry->pagelist[page_ofs]->virtual));
|
||||||
|
|
||||||
|
DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
|
||||||
|
virt_to_bus(entry->pagelist[page_ofs]->virtual),
|
||||||
|
entry->handle + tmp_ofs );
|
||||||
|
}
|
||||||
|
|
||||||
/* Set ring buffer size */
|
/* Set ring buffer size */
|
||||||
RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw );
|
RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw );
|
||||||
|
|
||||||
radeon_do_wait_for_idle( dev_priv );
|
radeon_do_wait_for_idle( dev_priv );
|
||||||
|
|
||||||
/* Turn off PCI GART */
|
|
||||||
tmp = RADEON_READ( RADEON_AIC_CNTL ) & ~RADEON_PCIGART_TRANSLATE_EN;
|
|
||||||
RADEON_WRITE( RADEON_AIC_CNTL, tmp );
|
|
||||||
|
|
||||||
/* Turn on bus mastering */
|
/* Turn on bus mastering */
|
||||||
tmp = RADEON_READ( RADEON_BUS_CNTL ) & ~RADEON_BUS_MASTER_DIS;
|
tmp = RADEON_READ( RADEON_BUS_CNTL ) & ~RADEON_BUS_MASTER_DIS;
|
||||||
RADEON_WRITE( RADEON_BUS_CNTL, tmp );
|
RADEON_WRITE( RADEON_BUS_CNTL, tmp );
|
||||||
|
@ -621,9 +641,11 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev )
|
||||||
static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
|
static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
|
||||||
{
|
{
|
||||||
drm_radeon_private_t *dev_priv;
|
drm_radeon_private_t *dev_priv;
|
||||||
int i;
|
struct list_head *list;
|
||||||
|
u32 tmp;
|
||||||
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
dev_priv = drm_alloc( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER );
|
dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER );
|
||||||
if ( dev_priv == NULL )
|
if ( dev_priv == NULL )
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
dev->dev_private = (void *)dev_priv;
|
dev->dev_private = (void *)dev_priv;
|
||||||
|
@ -632,12 +654,21 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
|
||||||
|
|
||||||
dev_priv->is_pci = init->is_pci;
|
dev_priv->is_pci = init->is_pci;
|
||||||
|
|
||||||
/* We don't support PCI cards until PCI GART is implemented.
|
#if 1
|
||||||
* Fail here so we can remove all checks for PCI cards around
|
/* PCI support is not 100% working, so we disable it here.
|
||||||
* the CP ring code.
|
|
||||||
*/
|
*/
|
||||||
if ( dev_priv->is_pci ) {
|
if ( dev_priv->is_pci ) {
|
||||||
drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
|
DRM_ERROR( "PCI GART not yet supported for Radeon!\n" );
|
||||||
|
DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
|
||||||
|
dev->dev_private = NULL;
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( dev_priv->is_pci && !dev->sg ) {
|
||||||
|
DRM_DEBUG( "PCI GART memory not allocated!\n" );
|
||||||
|
DRM_ERROR( "PCI GART memory not allocated!\n" );
|
||||||
|
DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
|
||||||
dev->dev_private = NULL;
|
dev->dev_private = NULL;
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -645,7 +676,8 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
|
||||||
dev_priv->usec_timeout = init->usec_timeout;
|
dev_priv->usec_timeout = init->usec_timeout;
|
||||||
if ( dev_priv->usec_timeout < 1 ||
|
if ( dev_priv->usec_timeout < 1 ||
|
||||||
dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) {
|
dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) {
|
||||||
drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
|
DRM_DEBUG( "TIMEOUT problem!\n" );
|
||||||
|
DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
|
||||||
dev->dev_private = NULL;
|
dev->dev_private = NULL;
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -662,7 +694,8 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
|
||||||
*/
|
*/
|
||||||
if ( ( init->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) &&
|
if ( ( init->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) &&
|
||||||
( init->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) {
|
( init->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) {
|
||||||
drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
|
DRM_DEBUG( "BAD cp_mode (%x)!\n", init->cp_mode );
|
||||||
|
DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
|
||||||
dev->dev_private = NULL;
|
dev->dev_private = NULL;
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -722,55 +755,78 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
|
||||||
RADEON_BFACE_SOLID |
|
RADEON_BFACE_SOLID |
|
||||||
RADEON_FFACE_SOLID |
|
RADEON_FFACE_SOLID |
|
||||||
RADEON_FLAT_SHADE_VTX_LAST |
|
RADEON_FLAT_SHADE_VTX_LAST |
|
||||||
|
|
||||||
RADEON_DIFFUSE_SHADE_FLAT |
|
RADEON_DIFFUSE_SHADE_FLAT |
|
||||||
RADEON_ALPHA_SHADE_FLAT |
|
RADEON_ALPHA_SHADE_FLAT |
|
||||||
RADEON_SPECULAR_SHADE_FLAT |
|
RADEON_SPECULAR_SHADE_FLAT |
|
||||||
RADEON_FOG_SHADE_FLAT |
|
RADEON_FOG_SHADE_FLAT |
|
||||||
|
|
||||||
RADEON_VTX_PIX_CENTER_OGL |
|
RADEON_VTX_PIX_CENTER_OGL |
|
||||||
RADEON_ROUND_MODE_TRUNC |
|
RADEON_ROUND_MODE_TRUNC |
|
||||||
RADEON_ROUND_PREC_8TH_PIX);
|
RADEON_ROUND_PREC_8TH_PIX);
|
||||||
|
|
||||||
/* FIXME: We want multiple shared areas, including one shared
|
list_for_each(list, &dev->maplist->head) {
|
||||||
* only by the X Server and kernel module.
|
drm_map_list_t *r_list = (drm_map_list_t *)list;
|
||||||
*/
|
if( r_list->map &&
|
||||||
for ( i = 0 ; i < dev->map_count ; i++ ) {
|
r_list->map->type == _DRM_SHM &&
|
||||||
if ( dev->maplist[i]->type == _DRM_SHM ) {
|
r_list->map->flags & _DRM_CONTAINS_LOCK ) {
|
||||||
dev_priv->sarea = dev->maplist[i];
|
dev_priv->sarea = r_list->map;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DO_FIND_MAP( dev_priv->fb, init->fb_offset );
|
DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
|
||||||
DO_FIND_MAP( dev_priv->mmio, init->mmio_offset );
|
DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
|
||||||
DO_FIND_MAP( dev_priv->cp_ring, init->ring_offset );
|
DRM_FIND_MAP( dev_priv->cp_ring, init->ring_offset );
|
||||||
DO_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
|
DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
|
||||||
DO_FIND_MAP( dev_priv->buffers, init->buffers_offset );
|
DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
|
||||||
|
|
||||||
if ( !dev_priv->is_pci ) {
|
if ( !dev_priv->is_pci ) {
|
||||||
DO_FIND_MAP( dev_priv->agp_textures,
|
DRM_FIND_MAP( dev_priv->agp_textures,
|
||||||
init->agp_textures_offset );
|
init->agp_textures_offset );
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_priv->sarea_priv =
|
dev_priv->sarea_priv =
|
||||||
(drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle +
|
(drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle +
|
||||||
init->sarea_priv_offset);
|
init->sarea_priv_offset);
|
||||||
|
|
||||||
DO_IOREMAP( dev_priv->cp_ring );
|
|
||||||
DO_IOREMAP( dev_priv->ring_rptr );
|
|
||||||
DO_IOREMAP( dev_priv->buffers );
|
|
||||||
#if 0
|
|
||||||
if ( !dev_priv->is_pci ) {
|
if ( !dev_priv->is_pci ) {
|
||||||
DO_IOREMAP( dev_priv->agp_textures );
|
DRM_IOREMAP( dev_priv->cp_ring );
|
||||||
|
DRM_IOREMAP( dev_priv->ring_rptr );
|
||||||
|
DRM_IOREMAP( dev_priv->buffers );
|
||||||
|
} else {
|
||||||
|
dev_priv->cp_ring->handle =
|
||||||
|
(void *)dev_priv->cp_ring->offset;
|
||||||
|
dev_priv->ring_rptr->handle =
|
||||||
|
(void *)dev_priv->ring_rptr->offset;
|
||||||
|
dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;
|
||||||
|
|
||||||
|
DRM_DEBUG( "dev_priv->cp_ring->handle %p\n",
|
||||||
|
dev_priv->cp_ring->handle );
|
||||||
|
DRM_DEBUG( "dev_priv->ring_rptr->handle %p\n",
|
||||||
|
dev_priv->ring_rptr->handle );
|
||||||
|
DRM_DEBUG( "dev_priv->buffers->handle %p\n",
|
||||||
|
dev_priv->buffers->handle );
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
dev_priv->agp_size = init->agp_size;
|
dev_priv->agp_size = init->agp_size;
|
||||||
dev_priv->agp_vm_start = RADEON_READ( RADEON_CONFIG_APER_SIZE );
|
dev_priv->agp_vm_start = RADEON_READ( RADEON_CONFIG_APER_SIZE );
|
||||||
dev_priv->agp_buffers_offset = (dev_priv->buffers->offset
|
#if __REALLY_HAVE_AGP
|
||||||
- dev->agp->base
|
if ( !dev_priv->is_pci )
|
||||||
+ dev_priv->agp_vm_start);
|
dev_priv->agp_buffers_offset = (dev_priv->buffers->offset
|
||||||
|
- dev->agp->base
|
||||||
|
+ dev_priv->agp_vm_start);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
dev_priv->agp_buffers_offset = (dev_priv->buffers->offset
|
||||||
|
- dev->sg->handle
|
||||||
|
+ dev_priv->agp_vm_start);
|
||||||
|
|
||||||
|
DRM_DEBUG( "dev_priv->agp_size %d\n",
|
||||||
|
dev_priv->agp_size );
|
||||||
|
DRM_DEBUG( "dev_priv->agp_vm_start 0x%x\n",
|
||||||
|
dev_priv->agp_vm_start );
|
||||||
|
DRM_DEBUG( "dev_priv->agp_buffers_offset 0x%lx\n",
|
||||||
|
dev_priv->agp_buffers_offset );
|
||||||
|
|
||||||
dev_priv->ring.head = ((__volatile__ u32 *)
|
dev_priv->ring.head = ((__volatile__ u32 *)
|
||||||
dev_priv->ring_rptr->handle);
|
dev_priv->ring_rptr->handle);
|
||||||
|
@ -779,11 +835,13 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
|
||||||
dev_priv->ring.end = ((u32 *)dev_priv->cp_ring->handle
|
dev_priv->ring.end = ((u32 *)dev_priv->cp_ring->handle
|
||||||
+ init->ring_size / sizeof(u32));
|
+ init->ring_size / sizeof(u32));
|
||||||
dev_priv->ring.size = init->ring_size;
|
dev_priv->ring.size = init->ring_size;
|
||||||
dev_priv->ring.size_l2qw = drm_order( init->ring_size / 8 );
|
dev_priv->ring.size_l2qw = DRM(order)( init->ring_size / 8 );
|
||||||
|
|
||||||
dev_priv->ring.tail_mask =
|
dev_priv->ring.tail_mask =
|
||||||
(dev_priv->ring.size / sizeof(u32)) - 1;
|
(dev_priv->ring.size / sizeof(u32)) - 1;
|
||||||
|
|
||||||
|
dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* Initialize the scratch register pointer. This will cause
|
/* Initialize the scratch register pointer. This will cause
|
||||||
* the scratch register values to be written out to memory
|
* the scratch register values to be written out to memory
|
||||||
|
@ -812,6 +870,44 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
|
||||||
RADEON_WRITE( RADEON_LAST_CLEAR_REG,
|
RADEON_WRITE( RADEON_LAST_CLEAR_REG,
|
||||||
dev_priv->sarea_priv->last_clear );
|
dev_priv->sarea_priv->last_clear );
|
||||||
|
|
||||||
|
if ( dev_priv->is_pci ) {
|
||||||
|
dev_priv->phys_pci_gart = DRM(ati_pcigart_init)( dev );
|
||||||
|
if ( !dev_priv->phys_pci_gart ) {
|
||||||
|
DRM_DEBUG( "failed to init PCI GART!\n" );
|
||||||
|
DRM_ERROR( "failed to init PCI GART!\n" );
|
||||||
|
DRM(free)( dev_priv, sizeof(*dev_priv),
|
||||||
|
DRM_MEM_DRIVER );
|
||||||
|
dev->dev_private = NULL;
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
/* Turn on PCI GART
|
||||||
|
*/
|
||||||
|
tmp = RADEON_READ( RADEON_AIC_CNTL )
|
||||||
|
| RADEON_PCIGART_TRANSLATE_EN;
|
||||||
|
RADEON_WRITE( RADEON_AIC_CNTL, tmp );
|
||||||
|
|
||||||
|
/* set PCI GART page-table base address
|
||||||
|
*/
|
||||||
|
RADEON_WRITE( RADEON_AIC_PT_BASE,
|
||||||
|
virt_to_bus( (void *)dev_priv->phys_pci_gart ) );
|
||||||
|
|
||||||
|
/* set address range for PCI address translate
|
||||||
|
*/
|
||||||
|
RADEON_WRITE( RADEON_AIC_LO_ADDR, dev_priv->agp_vm_start );
|
||||||
|
RADEON_WRITE( RADEON_AIC_HI_ADDR, dev_priv->agp_vm_start
|
||||||
|
+ dev_priv->agp_size - 1);
|
||||||
|
|
||||||
|
/* Turn off AGP aperture -- is this required for PCIGART?
|
||||||
|
*/
|
||||||
|
RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0 );
|
||||||
|
} else {
|
||||||
|
/* Turn off PCI GART
|
||||||
|
*/
|
||||||
|
tmp = RADEON_READ( RADEON_AIC_CNTL )
|
||||||
|
& ~RADEON_PCIGART_TRANSLATE_EN;
|
||||||
|
RADEON_WRITE( RADEON_AIC_CNTL, tmp );
|
||||||
|
}
|
||||||
|
|
||||||
radeon_cp_load_microcode( dev_priv );
|
radeon_cp_load_microcode( dev_priv );
|
||||||
radeon_cp_init_ring_buffer( dev );
|
radeon_cp_init_ring_buffer( dev );
|
||||||
radeon_do_engine_reset( dev );
|
radeon_do_engine_reset( dev );
|
||||||
|
@ -823,22 +919,21 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int radeon_do_cleanup_cp( drm_device_t *dev )
|
int radeon_do_cleanup_cp( drm_device_t *dev )
|
||||||
{
|
{
|
||||||
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
if ( dev->dev_private ) {
|
if ( dev->dev_private ) {
|
||||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||||
|
|
||||||
DO_IOREMAPFREE( dev_priv->cp_ring );
|
|
||||||
DO_IOREMAPFREE( dev_priv->ring_rptr );
|
|
||||||
DO_IOREMAPFREE( dev_priv->buffers );
|
|
||||||
#if 0
|
|
||||||
if ( !dev_priv->is_pci ) {
|
if ( !dev_priv->is_pci ) {
|
||||||
DO_IOREMAPFREE( dev_priv->agp_textures );
|
DRM_IOREMAPFREE( dev_priv->cp_ring );
|
||||||
|
DRM_IOREMAPFREE( dev_priv->ring_rptr );
|
||||||
|
DRM_IOREMAPFREE( dev_priv->buffers );
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
drm_free( dev->dev_private, sizeof(drm_radeon_private_t),
|
DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t),
|
||||||
DRM_MEM_DRIVER );
|
DRM_MEM_DRIVER );
|
||||||
dev->dev_private = NULL;
|
dev->dev_private = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -873,11 +968,8 @@ int radeon_cp_start( struct inode *inode, struct file *filp,
|
||||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
|
LOCK_TEST_WITH_RETURN( dev );
|
||||||
dev->lock.pid != current->pid ) {
|
|
||||||
DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
if ( dev_priv->cp_running ) {
|
if ( dev_priv->cp_running ) {
|
||||||
DRM_DEBUG( "%s while CP running\n", __FUNCTION__ );
|
DRM_DEBUG( "%s while CP running\n", __FUNCTION__ );
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -906,11 +998,7 @@ int radeon_cp_stop( struct inode *inode, struct file *filp,
|
||||||
int ret;
|
int ret;
|
||||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
|
LOCK_TEST_WITH_RETURN( dev );
|
||||||
dev->lock.pid != current->pid ) {
|
|
||||||
DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( copy_from_user( &stop, (drm_radeon_init_t *)arg, sizeof(stop) ) )
|
if ( copy_from_user( &stop, (drm_radeon_init_t *)arg, sizeof(stop) ) )
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
@ -952,11 +1040,8 @@ int radeon_cp_reset( struct inode *inode, struct file *filp,
|
||||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
|
LOCK_TEST_WITH_RETURN( dev );
|
||||||
dev->lock.pid != current->pid ) {
|
|
||||||
DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
if ( !dev_priv ) {
|
if ( !dev_priv ) {
|
||||||
DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
|
DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -978,11 +1063,7 @@ int radeon_cp_idle( struct inode *inode, struct file *filp,
|
||||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
|
LOCK_TEST_WITH_RETURN( dev );
|
||||||
dev->lock.pid != current->pid ) {
|
|
||||||
DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return radeon_do_cp_idle( dev_priv );
|
return radeon_do_cp_idle( dev_priv );
|
||||||
}
|
}
|
||||||
|
@ -994,11 +1075,7 @@ int radeon_engine_reset( struct inode *inode, struct file *filp,
|
||||||
drm_device_t *dev = priv->dev;
|
drm_device_t *dev = priv->dev;
|
||||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
|
LOCK_TEST_WITH_RETURN( dev );
|
||||||
dev->lock.pid != current->pid ) {
|
|
||||||
DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return radeon_do_engine_reset( dev );
|
return radeon_do_engine_reset( dev );
|
||||||
}
|
}
|
||||||
|
@ -1048,11 +1125,7 @@ int radeon_fullscreen( struct inode *inode, struct file *filp,
|
||||||
drm_device_t *dev = priv->dev;
|
drm_device_t *dev = priv->dev;
|
||||||
drm_radeon_fullscreen_t fs;
|
drm_radeon_fullscreen_t fs;
|
||||||
|
|
||||||
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
|
LOCK_TEST_WITH_RETURN( dev );
|
||||||
dev->lock.pid != current->pid ) {
|
|
||||||
DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( copy_from_user( &fs, (drm_radeon_fullscreen_t *)arg,
|
if ( copy_from_user( &fs, (drm_radeon_fullscreen_t *)arg,
|
||||||
sizeof(fs) ) )
|
sizeof(fs) ) )
|
||||||
|
@ -1085,8 +1158,8 @@ static int radeon_freelist_init( drm_device_t *dev )
|
||||||
drm_radeon_freelist_t *entry;
|
drm_radeon_freelist_t *entry;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
dev_priv->head = drm_alloc( sizeof(drm_radeon_freelist_t),
|
dev_priv->head = DRM(alloc)( sizeof(drm_radeon_freelist_t),
|
||||||
DRM_MEM_DRIVER );
|
DRM_MEM_DRIVER );
|
||||||
if ( dev_priv->head == NULL )
|
if ( dev_priv->head == NULL )
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -1097,8 +1170,8 @@ static int radeon_freelist_init( drm_device_t *dev )
|
||||||
buf = dma->buflist[i];
|
buf = dma->buflist[i];
|
||||||
buf_priv = buf->dev_private;
|
buf_priv = buf->dev_private;
|
||||||
|
|
||||||
entry = drm_alloc( sizeof(drm_radeon_freelist_t),
|
entry = DRM(alloc)( sizeof(drm_radeon_freelist_t),
|
||||||
DRM_MEM_DRIVER );
|
DRM_MEM_DRIVER );
|
||||||
if ( !entry ) return -ENOMEM;
|
if ( !entry ) return -ENOMEM;
|
||||||
|
|
||||||
entry->age = RADEON_BUFFER_FREE;
|
entry->age = RADEON_BUFFER_FREE;
|
||||||
|
@ -1218,32 +1291,20 @@ int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n )
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
|
for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
|
||||||
ring->space = *ring->head - ring->tail;
|
radeon_update_ring_snapshot( ring );
|
||||||
if ( ring->space <= 0 )
|
if ( ring->space > n )
|
||||||
ring->space += ring->size;
|
|
||||||
|
|
||||||
if ( ring->space >= n )
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
udelay( 1 );
|
udelay( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: This return value is ignored in the BEGIN_RING macro! */
|
/* FIXME: This return value is ignored in the BEGIN_RING macro! */
|
||||||
|
#if RADEON_FIFO_DEBUG
|
||||||
|
radeon_status( dev_priv );
|
||||||
DRM_ERROR( "failed!\n" );
|
DRM_ERROR( "failed!\n" );
|
||||||
|
#endif
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void radeon_update_ring_snapshot( drm_radeon_private_t *dev_priv )
|
|
||||||
{
|
|
||||||
drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
|
|
||||||
|
|
||||||
ring->space = *ring->head - ring->tail;
|
|
||||||
if ( ring->space == 0 )
|
|
||||||
atomic_inc( &dev_priv->idle_count );
|
|
||||||
if ( ring->space <= 0 )
|
|
||||||
ring->space += ring->size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int radeon_cp_get_buffers( drm_device_t *dev, drm_dma_t *d )
|
static int radeon_cp_get_buffers( drm_device_t *dev, drm_dma_t *d )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -1276,14 +1337,10 @@ int radeon_cp_buffers( struct inode *inode, struct file *filp,
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
drm_dma_t d;
|
drm_dma_t d;
|
||||||
|
|
||||||
if ( copy_from_user( &d, (drm_dma_t *) arg, sizeof(d) ) )
|
LOCK_TEST_WITH_RETURN( dev );
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
|
if ( copy_from_user( &d, (drm_dma_t *)arg, sizeof(d) ) )
|
||||||
dev->lock.pid != current->pid ) {
|
return -EFAULT;
|
||||||
DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Please don't send us buffers.
|
/* Please don't send us buffers.
|
||||||
*/
|
*/
|
||||||
|
@ -1307,7 +1364,7 @@ int radeon_cp_buffers( struct inode *inode, struct file *filp,
|
||||||
ret = radeon_cp_get_buffers( dev, &d );
|
ret = radeon_cp_get_buffers( dev, &d );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( copy_to_user( (drm_dma_t *) arg, &d, sizeof(d) ) )
|
if ( copy_to_user( (drm_dma_t *)arg, &d, sizeof(d) ) )
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
* Authors:
|
* Authors:
|
||||||
* Kevin E. Martin <martin@valinux.com>
|
* Kevin E. Martin <martin@valinux.com>
|
||||||
* Gareth Hughes <gareth@valinux.com>
|
* Gareth Hughes <gareth@valinux.com>
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __RADEON_DRM_H__
|
#ifndef __RADEON_DRM_H__
|
||||||
|
@ -74,7 +73,7 @@
|
||||||
|
|
||||||
/* Vertex/indirect buffer size
|
/* Vertex/indirect buffer size
|
||||||
*/
|
*/
|
||||||
#define RADEON_BUFFER_SIZE 16384
|
#define RADEON_BUFFER_SIZE 65536
|
||||||
|
|
||||||
/* Byte offsets for indirect buffer data
|
/* Byte offsets for indirect buffer data
|
||||||
*/
|
*/
|
||||||
|
@ -237,7 +236,7 @@ typedef struct drm_radeon_init {
|
||||||
RADEON_INIT_CP = 0x01,
|
RADEON_INIT_CP = 0x01,
|
||||||
RADEON_CLEANUP_CP = 0x02
|
RADEON_CLEANUP_CP = 0x02
|
||||||
} func;
|
} func;
|
||||||
int sarea_priv_offset;
|
unsigned long sarea_priv_offset;
|
||||||
int is_pci;
|
int is_pci;
|
||||||
int cp_mode;
|
int cp_mode;
|
||||||
int agp_size;
|
int agp_size;
|
||||||
|
@ -250,12 +249,12 @@ typedef struct drm_radeon_init {
|
||||||
unsigned int depth_bpp;
|
unsigned int depth_bpp;
|
||||||
unsigned int depth_offset, depth_pitch;
|
unsigned int depth_offset, depth_pitch;
|
||||||
|
|
||||||
unsigned int fb_offset;
|
unsigned long fb_offset;
|
||||||
unsigned int mmio_offset;
|
unsigned long mmio_offset;
|
||||||
unsigned int ring_offset;
|
unsigned long ring_offset;
|
||||||
unsigned int ring_rptr_offset;
|
unsigned long ring_rptr_offset;
|
||||||
unsigned int buffers_offset;
|
unsigned long buffers_offset;
|
||||||
unsigned int agp_textures_offset;
|
unsigned long agp_textures_offset;
|
||||||
} drm_radeon_init_t;
|
} drm_radeon_init_t;
|
||||||
|
|
||||||
typedef struct drm_radeon_cp_stop {
|
typedef struct drm_radeon_cp_stop {
|
||||||
|
@ -276,15 +275,18 @@ typedef struct drm_radeon_fullscreen {
|
||||||
#define CLEAR_Y2 3
|
#define CLEAR_Y2 3
|
||||||
#define CLEAR_DEPTH 4
|
#define CLEAR_DEPTH 4
|
||||||
|
|
||||||
|
typedef union drm_radeon_clear_rect {
|
||||||
|
float f[5];
|
||||||
|
unsigned int ui[5];
|
||||||
|
} drm_radeon_clear_rect_t;
|
||||||
|
|
||||||
typedef struct drm_radeon_clear {
|
typedef struct drm_radeon_clear {
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
int x, y, w, h;
|
|
||||||
unsigned int clear_color;
|
unsigned int clear_color;
|
||||||
unsigned int clear_depth;
|
unsigned int clear_depth;
|
||||||
union {
|
unsigned int color_mask;
|
||||||
float f[5];
|
unsigned int depth_mask;
|
||||||
unsigned int ui[5];
|
drm_radeon_clear_rect_t *depth_boxes;
|
||||||
} rect;
|
|
||||||
} drm_radeon_clear_t;
|
} drm_radeon_clear_t;
|
||||||
|
|
||||||
typedef struct drm_radeon_vertex {
|
typedef struct drm_radeon_vertex {
|
||||||
|
@ -302,14 +304,20 @@ typedef struct drm_radeon_indices {
|
||||||
int discard; /* Client finished with buffer? */
|
int discard; /* Client finished with buffer? */
|
||||||
} drm_radeon_indices_t;
|
} drm_radeon_indices_t;
|
||||||
|
|
||||||
typedef struct drm_radeon_blit {
|
typedef struct drm_radeon_tex_image {
|
||||||
int idx;
|
unsigned int x, y; /* Blit coordinates */
|
||||||
int pitch;
|
unsigned int width, height;
|
||||||
|
const void *data;
|
||||||
|
} drm_radeon_tex_image_t;
|
||||||
|
|
||||||
|
typedef struct drm_radeon_texture {
|
||||||
int offset;
|
int offset;
|
||||||
|
int pitch;
|
||||||
int format;
|
int format;
|
||||||
unsigned short x, y;
|
int width; /* Texture image coordinates */
|
||||||
unsigned short width, height;
|
int height;
|
||||||
} drm_radeon_blit_t;
|
drm_radeon_tex_image_t *image;
|
||||||
|
} drm_radeon_texture_t;
|
||||||
|
|
||||||
typedef struct drm_radeon_stipple {
|
typedef struct drm_radeon_stipple {
|
||||||
unsigned int *mask;
|
unsigned int *mask;
|
||||||
|
|
|
@ -31,16 +31,17 @@
|
||||||
#include "radeon.h"
|
#include "radeon.h"
|
||||||
#include "drmP.h"
|
#include "drmP.h"
|
||||||
#include "radeon_drv.h"
|
#include "radeon_drv.h"
|
||||||
|
#include "ati_pcigart.h"
|
||||||
|
|
||||||
#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc."
|
#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc."
|
||||||
|
|
||||||
#define DRIVER_NAME "radeon"
|
#define DRIVER_NAME "radeon"
|
||||||
#define DRIVER_DESC "ATI Radeon"
|
#define DRIVER_DESC "ATI Radeon"
|
||||||
#define DRIVER_DATE "20010402"
|
#define DRIVER_DATE "20010405"
|
||||||
|
|
||||||
#define DRIVER_MAJOR 1
|
#define DRIVER_MAJOR 1
|
||||||
#define DRIVER_MINOR 1
|
#define DRIVER_MINOR 1
|
||||||
#define DRIVER_PATCHLEVEL 0
|
#define DRIVER_PATCHLEVEL 1
|
||||||
|
|
||||||
#define DRIVER_IOCTLS \
|
#define DRIVER_IOCTLS \
|
||||||
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \
|
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \
|
||||||
|
@ -85,3 +86,4 @@
|
||||||
#include "drm_proc.h"
|
#include "drm_proc.h"
|
||||||
#include "drm_vm.h"
|
#include "drm_vm.h"
|
||||||
#include "drm_stub.h"
|
#include "drm_stub.h"
|
||||||
|
#include "drm_scatter.h"
|
||||||
|
|
|
@ -24,10 +24,8 @@
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
* Kevin E. Martin <martin@valinux.com>
|
||||||
* Kevin E. Martin <martin@valinux.com>
|
* Gareth Hughes <gareth@valinux.com>
|
||||||
* Gareth Hughes <gareth@valinux.com>
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __RADEON_DRV_H__
|
#ifndef __RADEON_DRV_H__
|
||||||
|
@ -50,6 +48,8 @@ typedef struct drm_radeon_ring_buffer {
|
||||||
u32 tail;
|
u32 tail;
|
||||||
u32 tail_mask;
|
u32 tail_mask;
|
||||||
int space;
|
int space;
|
||||||
|
|
||||||
|
int high_mark;
|
||||||
} drm_radeon_ring_buffer_t;
|
} drm_radeon_ring_buffer_t;
|
||||||
|
|
||||||
typedef struct drm_radeon_depth_clear_t {
|
typedef struct drm_radeon_depth_clear_t {
|
||||||
|
@ -64,7 +64,7 @@ typedef struct drm_radeon_private {
|
||||||
|
|
||||||
int agp_size;
|
int agp_size;
|
||||||
u32 agp_vm_start;
|
u32 agp_vm_start;
|
||||||
u32 agp_buffers_offset;
|
unsigned long agp_buffers_offset;
|
||||||
|
|
||||||
int cp_mode;
|
int cp_mode;
|
||||||
int cp_running;
|
int cp_running;
|
||||||
|
@ -83,6 +83,7 @@ typedef struct drm_radeon_private {
|
||||||
|
|
||||||
int usec_timeout;
|
int usec_timeout;
|
||||||
int is_pci;
|
int is_pci;
|
||||||
|
unsigned long phys_pci_gart;
|
||||||
|
|
||||||
atomic_t idle_count;
|
atomic_t idle_count;
|
||||||
|
|
||||||
|
@ -91,13 +92,13 @@ typedef struct drm_radeon_private {
|
||||||
u32 crtc_offset;
|
u32 crtc_offset;
|
||||||
u32 crtc_offset_cntl;
|
u32 crtc_offset_cntl;
|
||||||
|
|
||||||
unsigned int color_fmt;
|
u32 color_fmt;
|
||||||
unsigned int front_offset;
|
unsigned int front_offset;
|
||||||
unsigned int front_pitch;
|
unsigned int front_pitch;
|
||||||
unsigned int back_offset;
|
unsigned int back_offset;
|
||||||
unsigned int back_pitch;
|
unsigned int back_pitch;
|
||||||
|
|
||||||
unsigned int depth_fmt;
|
u32 depth_fmt;
|
||||||
unsigned int depth_offset;
|
unsigned int depth_offset;
|
||||||
unsigned int depth_pitch;
|
unsigned int depth_pitch;
|
||||||
|
|
||||||
|
@ -124,18 +125,6 @@ typedef struct drm_radeon_buf_priv {
|
||||||
drm_radeon_freelist_t *list_entry;
|
drm_radeon_freelist_t *list_entry;
|
||||||
} drm_radeon_buf_priv_t;
|
} drm_radeon_buf_priv_t;
|
||||||
|
|
||||||
/* radeon_drv.c */
|
|
||||||
extern int radeon_version( struct inode *inode, struct file *filp,
|
|
||||||
unsigned int cmd, unsigned long arg );
|
|
||||||
extern int radeon_open( struct inode *inode, struct file *filp );
|
|
||||||
extern int radeon_release( struct inode *inode, struct file *filp );
|
|
||||||
extern int radeon_ioctl( struct inode *inode, struct file *filp,
|
|
||||||
unsigned int cmd, unsigned long arg );
|
|
||||||
extern int radeon_lock( struct inode *inode, struct file *filp,
|
|
||||||
unsigned int cmd, unsigned long arg );
|
|
||||||
extern int radeon_unlock( struct inode *inode, struct file *filp,
|
|
||||||
unsigned int cmd, unsigned long arg );
|
|
||||||
|
|
||||||
/* radeon_cp.c */
|
/* radeon_cp.c */
|
||||||
extern int radeon_cp_init( struct inode *inode, struct file *filp,
|
extern int radeon_cp_init( struct inode *inode, struct file *filp,
|
||||||
unsigned int cmd, unsigned long arg );
|
unsigned int cmd, unsigned long arg );
|
||||||
|
@ -158,9 +147,17 @@ extern void radeon_freelist_reset( drm_device_t *dev );
|
||||||
extern drm_buf_t *radeon_freelist_get( drm_device_t *dev );
|
extern drm_buf_t *radeon_freelist_get( drm_device_t *dev );
|
||||||
|
|
||||||
extern int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n );
|
extern int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n );
|
||||||
extern void radeon_update_ring_snapshot( drm_radeon_private_t *dev_priv );
|
|
||||||
|
static inline void
|
||||||
|
radeon_update_ring_snapshot( drm_radeon_ring_buffer_t *ring )
|
||||||
|
{
|
||||||
|
ring->space = (*(volatile int *)ring->head - ring->tail) * sizeof(u32);
|
||||||
|
if ( ring->space <= 0 )
|
||||||
|
ring->space += ring->size;
|
||||||
|
}
|
||||||
|
|
||||||
extern int radeon_do_cp_idle( drm_radeon_private_t *dev_priv );
|
extern int radeon_do_cp_idle( drm_radeon_private_t *dev_priv );
|
||||||
|
extern int radeon_do_cleanup_cp( drm_device_t *dev );
|
||||||
extern int radeon_do_cleanup_pageflip( drm_device_t *dev );
|
extern int radeon_do_cleanup_pageflip( drm_device_t *dev );
|
||||||
|
|
||||||
/* radeon_state.c */
|
/* radeon_state.c */
|
||||||
|
@ -172,38 +169,13 @@ extern int radeon_cp_vertex( struct inode *inode, struct file *filp,
|
||||||
unsigned int cmd, unsigned long arg );
|
unsigned int cmd, unsigned long arg );
|
||||||
extern int radeon_cp_indices( struct inode *inode, struct file *filp,
|
extern int radeon_cp_indices( struct inode *inode, struct file *filp,
|
||||||
unsigned int cmd, unsigned long arg );
|
unsigned int cmd, unsigned long arg );
|
||||||
extern int radeon_cp_blit( struct inode *inode, struct file *filp,
|
extern int radeon_cp_texture( struct inode *inode, struct file *filp,
|
||||||
unsigned int cmd, unsigned long arg );
|
unsigned int cmd, unsigned long arg );
|
||||||
extern int radeon_cp_stipple( struct inode *inode, struct file *filp,
|
extern int radeon_cp_stipple( struct inode *inode, struct file *filp,
|
||||||
unsigned int cmd, unsigned long arg );
|
unsigned int cmd, unsigned long arg );
|
||||||
extern int radeon_cp_indirect( struct inode *inode, struct file *filp,
|
extern int radeon_cp_indirect( struct inode *inode, struct file *filp,
|
||||||
unsigned int cmd, unsigned long arg );
|
unsigned int cmd, unsigned long arg );
|
||||||
|
|
||||||
/* radeon_bufs.c */
|
|
||||||
extern int radeon_addbufs(struct inode *inode, struct file *filp,
|
|
||||||
unsigned int cmd, unsigned long arg);
|
|
||||||
extern int radeon_mapbufs(struct inode *inode, struct file *filp,
|
|
||||||
unsigned int cmd, unsigned long arg);
|
|
||||||
|
|
||||||
/* radeon_context.c */
|
|
||||||
extern int radeon_resctx(struct inode *inode, struct file *filp,
|
|
||||||
unsigned int cmd, unsigned long arg);
|
|
||||||
extern int radeon_addctx(struct inode *inode, struct file *filp,
|
|
||||||
unsigned int cmd, unsigned long arg);
|
|
||||||
extern int radeon_modctx(struct inode *inode, struct file *filp,
|
|
||||||
unsigned int cmd, unsigned long arg);
|
|
||||||
extern int radeon_getctx(struct inode *inode, struct file *filp,
|
|
||||||
unsigned int cmd, unsigned long arg);
|
|
||||||
extern int radeon_switchctx(struct inode *inode, struct file *filp,
|
|
||||||
unsigned int cmd, unsigned long arg);
|
|
||||||
extern int radeon_newctx(struct inode *inode, struct file *filp,
|
|
||||||
unsigned int cmd, unsigned long arg);
|
|
||||||
extern int radeon_rmctx(struct inode *inode, struct file *filp,
|
|
||||||
unsigned int cmd, unsigned long arg);
|
|
||||||
|
|
||||||
extern int radeon_context_switch(drm_device_t *dev, int old, int new);
|
|
||||||
extern int radeon_context_switch_complete(drm_device_t *dev, int new);
|
|
||||||
|
|
||||||
|
|
||||||
/* Register definitions, register access macros and drmAddMap constants
|
/* Register definitions, register access macros and drmAddMap constants
|
||||||
* for Radeon kernel driver.
|
* for Radeon kernel driver.
|
||||||
|
@ -462,6 +434,12 @@ extern int radeon_context_switch_complete(drm_device_t *dev, int new);
|
||||||
|
|
||||||
#define RADEON_AIC_CNTL 0x01d0
|
#define RADEON_AIC_CNTL 0x01d0
|
||||||
# define RADEON_PCIGART_TRANSLATE_EN (1 << 0)
|
# define RADEON_PCIGART_TRANSLATE_EN (1 << 0)
|
||||||
|
#define RADEON_AIC_STAT 0x01d4
|
||||||
|
#define RADEON_AIC_PT_BASE 0x01d8
|
||||||
|
#define RADEON_AIC_LO_ADDR 0x01dc
|
||||||
|
#define RADEON_AIC_HI_ADDR 0x01e0
|
||||||
|
#define RADEON_AIC_TLB_ADDR 0x01e4
|
||||||
|
#define RADEON_AIC_TLB_DATA 0x01e8
|
||||||
|
|
||||||
/* CP command packets */
|
/* CP command packets */
|
||||||
#define RADEON_CP_PACKET0 0x00000000
|
#define RADEON_CP_PACKET0 0x00000000
|
||||||
|
@ -514,14 +492,14 @@ extern int radeon_context_switch_complete(drm_device_t *dev, int new);
|
||||||
#define RADEON_COLOR_FORMAT_RGB8 9
|
#define RADEON_COLOR_FORMAT_RGB8 9
|
||||||
#define RADEON_COLOR_FORMAT_ARGB4444 15
|
#define RADEON_COLOR_FORMAT_ARGB4444 15
|
||||||
|
|
||||||
#define RADEON_TXF_8BPP_I 0
|
#define RADEON_TXFORMAT_I8 0
|
||||||
#define RADEON_TXF_16BPP_AI88 1
|
#define RADEON_TXFORMAT_AI88 1
|
||||||
#define RADEON_TXF_8BPP_RGB332 2
|
#define RADEON_TXFORMAT_RGB332 2
|
||||||
#define RADEON_TXF_16BPP_ARGB1555 3
|
#define RADEON_TXFORMAT_ARGB1555 3
|
||||||
#define RADEON_TXF_16BPP_RGB565 4
|
#define RADEON_TXFORMAT_RGB565 4
|
||||||
#define RADEON_TXF_16BPP_ARGB4444 5
|
#define RADEON_TXFORMAT_ARGB4444 5
|
||||||
#define RADEON_TXF_32BPP_ARGB8888 6
|
#define RADEON_TXFORMAT_ARGB8888 6
|
||||||
#define RADEON_TXF_32BPP_RGBA8888 7
|
#define RADEON_TXFORMAT_RGBA8888 7
|
||||||
|
|
||||||
/* Constants */
|
/* Constants */
|
||||||
#define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */
|
#define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */
|
||||||
|
@ -534,27 +512,51 @@ extern int radeon_context_switch_complete(drm_device_t *dev, int new);
|
||||||
#define RADEON_MAX_VB_AGE 0x7fffffff
|
#define RADEON_MAX_VB_AGE 0x7fffffff
|
||||||
#define RADEON_MAX_VB_VERTS (0xffff)
|
#define RADEON_MAX_VB_VERTS (0xffff)
|
||||||
|
|
||||||
|
#define RADEON_RING_HIGH_MARK 128
|
||||||
|
|
||||||
#define RADEON_BASE(reg) ((u32)(dev_priv->mmio->handle))
|
|
||||||
#define RADEON_ADDR(reg) (RADEON_BASE(reg) + reg)
|
|
||||||
|
|
||||||
#define RADEON_DEREF(reg) *(__volatile__ u32 *)RADEON_ADDR(reg)
|
#define RADEON_BASE(reg) ((unsigned long)(dev_priv->mmio->handle))
|
||||||
#define RADEON_READ(reg) RADEON_DEREF(reg)
|
#define RADEON_ADDR(reg) (RADEON_BASE( reg ) + reg)
|
||||||
#define RADEON_WRITE(reg,val) do { RADEON_DEREF(reg) = val; } while (0)
|
|
||||||
|
|
||||||
#define RADEON_DEREF8(reg) *(__volatile__ u8 *)RADEON_ADDR(reg)
|
#define RADEON_DEREF(reg) *(volatile u32 *)RADEON_ADDR( reg )
|
||||||
#define RADEON_READ8(reg) RADEON_DEREF8(reg)
|
#ifdef __alpha__
|
||||||
#define RADEON_WRITE8(reg,val) do { RADEON_DEREF8(reg) = val; } while (0)
|
#define RADEON_READ(reg) (_RADEON_READ((u32 *)RADEON_ADDR( reg )))
|
||||||
|
static inline u32 _RADEON_READ(u32 *addr) {
|
||||||
|
mb();
|
||||||
|
return *(volatile u32 *)addr;
|
||||||
|
}
|
||||||
|
#define RADEON_WRITE(reg,val) do { \
|
||||||
|
wmb();
|
||||||
|
RADEON_DEREF(reg) = val;
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define RADEON_READ(reg) RADEON_DEREF( reg )
|
||||||
|
#define RADEON_WRITE(reg, val) do { RADEON_DEREF( reg ) = val; } while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define RADEON_WRITE_PLL(addr,val) \
|
#define RADEON_DEREF8(reg) *(volatile u8 *)RADEON_ADDR( reg )
|
||||||
do { \
|
#ifdef __alpha__
|
||||||
RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, \
|
#define RADEON_READ8(reg) _RADEON_READ8((u8 *)RADEON_ADDR( reg ))
|
||||||
((addr) & 0x1f) | RADEON_PLL_WR_EN); \
|
static inline u8 _RADEON_READ8(u8 *addr) {
|
||||||
RADEON_WRITE(RADEON_CLOCK_CNTL_DATA, (val)); \
|
mb();
|
||||||
|
return *(volatile u8 *)addr;
|
||||||
|
}
|
||||||
|
#define RADEON_WRITE8(reg,val) do { \
|
||||||
|
wmb();
|
||||||
|
RADEON_DEREF8( reg ) = val;
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define RADEON_READ8(reg) RADEON_DEREF8( reg )
|
||||||
|
#define RADEON_WRITE8(reg, val) do { RADEON_DEREF8( reg ) = val; } while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RADEON_WRITE_PLL( addr, val ) do { \
|
||||||
|
RADEON_WRITE8( RADEON_CLOCK_CNTL_INDEX, \
|
||||||
|
((addr) & 0x1f) | RADEON_PLL_WR_EN ); \
|
||||||
|
RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
extern int RADEON_READ_PLL(drm_device_t *dev, int addr);
|
extern int RADEON_READ_PLL( drm_device_t *dev, int addr );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define CP_PACKET0( reg, n ) \
|
#define CP_PACKET0( reg, n ) \
|
||||||
|
@ -573,54 +575,46 @@ extern int RADEON_READ_PLL(drm_device_t *dev, int addr);
|
||||||
* Engine control helper macros
|
* Engine control helper macros
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define RADEON_WAIT_UNTIL_2D_IDLE() \
|
#define RADEON_WAIT_UNTIL_2D_IDLE() do { \
|
||||||
do { \
|
|
||||||
OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
|
OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
|
||||||
OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \
|
OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \
|
||||||
RADEON_WAIT_HOST_IDLECLEAN) ); \
|
RADEON_WAIT_HOST_IDLECLEAN) ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define RADEON_WAIT_UNTIL_3D_IDLE() \
|
#define RADEON_WAIT_UNTIL_3D_IDLE() do { \
|
||||||
do { \
|
|
||||||
OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
|
OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
|
||||||
OUT_RING( (RADEON_WAIT_3D_IDLECLEAN | \
|
OUT_RING( (RADEON_WAIT_3D_IDLECLEAN | \
|
||||||
RADEON_WAIT_HOST_IDLECLEAN) ); \
|
RADEON_WAIT_HOST_IDLECLEAN) ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define RADEON_WAIT_UNTIL_IDLE() \
|
#define RADEON_WAIT_UNTIL_IDLE() do { \
|
||||||
do { \
|
|
||||||
OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
|
OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
|
||||||
OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \
|
OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \
|
||||||
RADEON_WAIT_3D_IDLECLEAN | \
|
RADEON_WAIT_3D_IDLECLEAN | \
|
||||||
RADEON_WAIT_HOST_IDLECLEAN) ); \
|
RADEON_WAIT_HOST_IDLECLEAN) ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define RADEON_WAIT_UNTIL_PAGE_FLIPPED() \
|
#define RADEON_WAIT_UNTIL_PAGE_FLIPPED() do { \
|
||||||
do { \
|
|
||||||
OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
|
OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
|
||||||
OUT_RING( RADEON_WAIT_CRTC_PFLIP ); \
|
OUT_RING( RADEON_WAIT_CRTC_PFLIP ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define RADEON_FLUSH_CACHE() \
|
#define RADEON_FLUSH_CACHE() do { \
|
||||||
do { \
|
|
||||||
OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \
|
OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \
|
||||||
OUT_RING( RADEON_RB2D_DC_FLUSH ); \
|
OUT_RING( RADEON_RB2D_DC_FLUSH ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define RADEON_PURGE_CACHE() \
|
#define RADEON_PURGE_CACHE() do { \
|
||||||
do { \
|
|
||||||
OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \
|
OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \
|
||||||
OUT_RING( RADEON_RB2D_DC_FLUSH_ALL ); \
|
OUT_RING( RADEON_RB2D_DC_FLUSH_ALL ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define RADEON_FLUSH_ZCACHE() \
|
#define RADEON_FLUSH_ZCACHE() do { \
|
||||||
do { \
|
|
||||||
OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) ); \
|
OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) ); \
|
||||||
OUT_RING( RADEON_RB3D_ZC_FLUSH ); \
|
OUT_RING( RADEON_RB3D_ZC_FLUSH ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define RADEON_PURGE_ZCACHE() \
|
#define RADEON_PURGE_ZCACHE() do { \
|
||||||
do { \
|
|
||||||
OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) ); \
|
OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) ); \
|
||||||
OUT_RING( RADEON_RB3D_ZC_FLUSH_ALL ); \
|
OUT_RING( RADEON_RB3D_ZC_FLUSH_ALL ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
@ -630,7 +624,33 @@ do { \
|
||||||
* Misc helper macros
|
* Misc helper macros
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define VB_AGE_CHECK_WITH_RET( dev_priv ) \
|
#define LOCK_TEST_WITH_RETURN( dev ) \
|
||||||
|
do { \
|
||||||
|
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \
|
||||||
|
dev->lock.pid != current->pid ) { \
|
||||||
|
DRM_ERROR( "%s called without lock held\n", \
|
||||||
|
__FUNCTION__ ); \
|
||||||
|
return -EINVAL; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \
|
||||||
|
do { \
|
||||||
|
drm_radeon_ring_buffer_t *ring = &dev_priv->ring; int i; \
|
||||||
|
if ( ring->space < ring->high_mark ) { \
|
||||||
|
for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { \
|
||||||
|
radeon_update_ring_snapshot( ring ); \
|
||||||
|
if ( ring->space >= ring->high_mark ) \
|
||||||
|
goto __ring_space_done; \
|
||||||
|
udelay( 1 ); \
|
||||||
|
} \
|
||||||
|
DRM_ERROR( "ring space check failed!\n" ); \
|
||||||
|
return -EBUSY; \
|
||||||
|
} \
|
||||||
|
__ring_space_done: \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define VB_AGE_TEST_WITH_RETURN( dev_priv ) \
|
||||||
do { \
|
do { \
|
||||||
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; \
|
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; \
|
||||||
if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) { \
|
if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) { \
|
||||||
|
@ -641,20 +661,17 @@ do { \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define RADEON_DISPATCH_AGE( age ) \
|
#define RADEON_DISPATCH_AGE( age ) do { \
|
||||||
do { \
|
|
||||||
OUT_RING( CP_PACKET0( RADEON_LAST_DISPATCH_REG, 0 ) ); \
|
OUT_RING( CP_PACKET0( RADEON_LAST_DISPATCH_REG, 0 ) ); \
|
||||||
OUT_RING( age ); \
|
OUT_RING( age ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define RADEON_FRAME_AGE( age ) \
|
#define RADEON_FRAME_AGE( age ) do { \
|
||||||
do { \
|
|
||||||
OUT_RING( CP_PACKET0( RADEON_LAST_FRAME_REG, 0 ) ); \
|
OUT_RING( CP_PACKET0( RADEON_LAST_FRAME_REG, 0 ) ); \
|
||||||
OUT_RING( age ); \
|
OUT_RING( age ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define RADEON_CLEAR_AGE( age ) \
|
#define RADEON_CLEAR_AGE( age ) do { \
|
||||||
do { \
|
|
||||||
OUT_RING( CP_PACKET0( RADEON_LAST_CLEAR_REG, 0 ) ); \
|
OUT_RING( CP_PACKET0( RADEON_LAST_CLEAR_REG, 0 ) ); \
|
||||||
OUT_RING( age ); \
|
OUT_RING( age ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
@ -676,7 +693,7 @@ do { \
|
||||||
DRM_INFO( "BEGIN_RING( %d ) in %s\n", \
|
DRM_INFO( "BEGIN_RING( %d ) in %s\n", \
|
||||||
n, __FUNCTION__ ); \
|
n, __FUNCTION__ ); \
|
||||||
} \
|
} \
|
||||||
if ( dev_priv->ring.space < (n) * sizeof(u32) ) { \
|
if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \
|
||||||
radeon_wait_ring( dev_priv, (n) * sizeof(u32) ); \
|
radeon_wait_ring( dev_priv, (n) * sizeof(u32) ); \
|
||||||
} \
|
} \
|
||||||
dev_priv->ring.space -= (n) * sizeof(u32); \
|
dev_priv->ring.space -= (n) * sizeof(u32); \
|
||||||
|
@ -687,7 +704,7 @@ do { \
|
||||||
|
|
||||||
#define ADVANCE_RING() do { \
|
#define ADVANCE_RING() do { \
|
||||||
if ( RADEON_VERBOSE ) { \
|
if ( RADEON_VERBOSE ) { \
|
||||||
DRM_INFO( "ADVANCE_RING() tail=0x%06x wr=0x%06x\n", \
|
DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \
|
||||||
write, dev_priv->ring.tail ); \
|
write, dev_priv->ring.tail ); \
|
||||||
} \
|
} \
|
||||||
radeon_flush_write_combine(); \
|
radeon_flush_write_combine(); \
|
||||||
|
|
|
@ -23,12 +23,12 @@
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Kevin E. Martin <martin@valinux.com>
|
|
||||||
* Gareth Hughes <gareth@valinux.com>
|
* Gareth Hughes <gareth@valinux.com>
|
||||||
*
|
* Kevin E. Martin <martin@valinux.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define __NO_VERSION__
|
#define __NO_VERSION__
|
||||||
|
#include "radeon.h"
|
||||||
#include "drmP.h"
|
#include "drmP.h"
|
||||||
#include "radeon_drv.h"
|
#include "radeon_drv.h"
|
||||||
#include "drm.h"
|
#include "drm.h"
|
||||||
|
@ -486,7 +486,8 @@ static void radeon_print_dirty( const char *msg, unsigned int flags )
|
||||||
}
|
}
|
||||||
|
|
||||||
static void radeon_cp_dispatch_clear( drm_device_t *dev,
|
static void radeon_cp_dispatch_clear( drm_device_t *dev,
|
||||||
drm_radeon_clear_t *clear )
|
drm_radeon_clear_t *clear,
|
||||||
|
drm_radeon_clear_rect_t *depth_boxes )
|
||||||
{
|
{
|
||||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||||
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||||
|
@ -497,8 +498,6 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev,
|
||||||
RING_LOCALS;
|
RING_LOCALS;
|
||||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
radeon_update_ring_snapshot( dev_priv );
|
|
||||||
|
|
||||||
if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
|
if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
|
||||||
unsigned int tmp = flags;
|
unsigned int tmp = flags;
|
||||||
|
|
||||||
|
@ -525,7 +524,7 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev,
|
||||||
RADEON_WAIT_UNTIL_3D_IDLE();
|
RADEON_WAIT_UNTIL_3D_IDLE();
|
||||||
|
|
||||||
OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
|
OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
|
||||||
OUT_RING( sarea_priv->context_state.rb3d_planemask );
|
OUT_RING( clear->color_mask );
|
||||||
|
|
||||||
ADVANCE_RING();
|
ADVANCE_RING();
|
||||||
|
|
||||||
|
@ -609,17 +608,17 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev,
|
||||||
RADEON_VTX_FMT_RADEON_MODE |
|
RADEON_VTX_FMT_RADEON_MODE |
|
||||||
(3 << RADEON_NUM_VERTICES_SHIFT)) );
|
(3 << RADEON_NUM_VERTICES_SHIFT)) );
|
||||||
|
|
||||||
OUT_RING( clear->rect.ui[CLEAR_X1] );
|
OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
|
||||||
OUT_RING( clear->rect.ui[CLEAR_Y1] );
|
OUT_RING( depth_boxes[i].ui[CLEAR_Y1] );
|
||||||
OUT_RING( clear->rect.ui[CLEAR_DEPTH] );
|
OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
|
||||||
|
|
||||||
OUT_RING( clear->rect.ui[CLEAR_X1] );
|
OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
|
||||||
OUT_RING( clear->rect.ui[CLEAR_Y2] );
|
OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
|
||||||
OUT_RING( clear->rect.ui[CLEAR_DEPTH] );
|
OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
|
||||||
|
|
||||||
OUT_RING( clear->rect.ui[CLEAR_X2] );
|
OUT_RING( depth_boxes[i].ui[CLEAR_X2] );
|
||||||
OUT_RING( clear->rect.ui[CLEAR_Y2] );
|
OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
|
||||||
OUT_RING( clear->rect.ui[CLEAR_DEPTH] );
|
OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
|
||||||
|
|
||||||
ADVANCE_RING();
|
ADVANCE_RING();
|
||||||
|
|
||||||
|
@ -655,8 +654,6 @@ static void radeon_cp_dispatch_swap( drm_device_t *dev )
|
||||||
RING_LOCALS;
|
RING_LOCALS;
|
||||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
radeon_update_ring_snapshot( dev_priv );
|
|
||||||
|
|
||||||
#if RADEON_PERFORMANCE_BOXES
|
#if RADEON_PERFORMANCE_BOXES
|
||||||
/* Do some trivial performance monitoring...
|
/* Do some trivial performance monitoring...
|
||||||
*/
|
*/
|
||||||
|
@ -724,8 +721,6 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev )
|
||||||
RING_LOCALS;
|
RING_LOCALS;
|
||||||
DRM_DEBUG( "%s: page=%d\n", __FUNCTION__, dev_priv->current_page );
|
DRM_DEBUG( "%s: page=%d\n", __FUNCTION__, dev_priv->current_page );
|
||||||
|
|
||||||
radeon_update_ring_snapshot( dev_priv );
|
|
||||||
|
|
||||||
#if RADEON_PERFORMANCE_BOXES
|
#if RADEON_PERFORMANCE_BOXES
|
||||||
/* Do some trivial performance monitoring...
|
/* Do some trivial performance monitoring...
|
||||||
*/
|
*/
|
||||||
|
@ -776,9 +771,7 @@ static void radeon_cp_dispatch_vertex( drm_device_t *dev,
|
||||||
RING_LOCALS;
|
RING_LOCALS;
|
||||||
DRM_DEBUG( "%s: nbox=%d\n", __FUNCTION__, sarea_priv->nbox );
|
DRM_DEBUG( "%s: nbox=%d\n", __FUNCTION__, sarea_priv->nbox );
|
||||||
|
|
||||||
radeon_update_ring_snapshot( dev_priv );
|
if ( 0 )
|
||||||
|
|
||||||
if ( 1 )
|
|
||||||
radeon_print_dirty( "dispatch_vertex", sarea_priv->dirty );
|
radeon_print_dirty( "dispatch_vertex", sarea_priv->dirty );
|
||||||
|
|
||||||
if ( buf->used ) {
|
if ( buf->used ) {
|
||||||
|
@ -844,8 +837,6 @@ static void radeon_cp_dispatch_indirect( drm_device_t *dev,
|
||||||
DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
|
DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
|
||||||
buf->idx, start, end );
|
buf->idx, start, end );
|
||||||
|
|
||||||
radeon_update_ring_snapshot( dev_priv );
|
|
||||||
|
|
||||||
if ( start != end ) {
|
if ( start != end ) {
|
||||||
int offset = (dev_priv->agp_buffers_offset
|
int offset = (dev_priv->agp_buffers_offset
|
||||||
+ buf->offset + start);
|
+ buf->offset + start);
|
||||||
|
@ -908,8 +899,6 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev,
|
||||||
RING_LOCALS;
|
RING_LOCALS;
|
||||||
DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
|
DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
|
||||||
|
|
||||||
radeon_update_ring_snapshot( dev_priv );
|
|
||||||
|
|
||||||
if ( 0 )
|
if ( 0 )
|
||||||
radeon_print_dirty( "dispatch_indices", sarea_priv->dirty );
|
radeon_print_dirty( "dispatch_indices", sarea_priv->dirty );
|
||||||
|
|
||||||
|
@ -971,50 +960,67 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev,
|
||||||
sarea_priv->nbox = 0;
|
sarea_priv->nbox = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int radeon_cp_dispatch_blit( drm_device_t *dev,
|
#define RADEON_MAX_TEXTURE_SIZE (RADEON_BUFFER_SIZE - 8 * sizeof(u32))
|
||||||
drm_radeon_blit_t *blit )
|
|
||||||
|
static int radeon_cp_dispatch_texture( drm_device_t *dev,
|
||||||
|
drm_radeon_texture_t *tex,
|
||||||
|
drm_radeon_tex_image_t *image )
|
||||||
{
|
{
|
||||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||||
drm_device_dma_t *dma = dev->dma;
|
|
||||||
drm_buf_t *buf;
|
drm_buf_t *buf;
|
||||||
drm_radeon_buf_priv_t *buf_priv;
|
drm_radeon_buf_priv_t *buf_priv;
|
||||||
u32 format;
|
u32 format;
|
||||||
u32 *data;
|
u32 *buffer;
|
||||||
int dword_shift, dwords;
|
u8 *data;
|
||||||
|
int size, dwords, tex_width, blit_width;
|
||||||
|
u32 y, height;
|
||||||
|
int ret = 0, i;
|
||||||
RING_LOCALS;
|
RING_LOCALS;
|
||||||
DRM_DEBUG( "blit: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
|
|
||||||
blit->offset >> 10, blit->pitch, blit->format,
|
|
||||||
blit->x, blit->y, blit->width, blit->height );
|
|
||||||
|
|
||||||
radeon_update_ring_snapshot( dev_priv );
|
/* FIXME: Be smarter about this...
|
||||||
|
*/
|
||||||
|
buf = radeon_freelist_get( dev );
|
||||||
|
if ( !buf ) return -EAGAIN;
|
||||||
|
|
||||||
|
DRM_DEBUG( "tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
|
||||||
|
tex->offset >> 10, tex->pitch, tex->format,
|
||||||
|
image->x, image->y, image->width, image->height );
|
||||||
|
|
||||||
|
buf_priv = buf->dev_private;
|
||||||
|
|
||||||
/* The compiler won't optimize away a division by a variable,
|
/* The compiler won't optimize away a division by a variable,
|
||||||
* even if the only legal values are powers of two. Thus, we'll
|
* even if the only legal values are powers of two. Thus, we'll
|
||||||
* use a shift instead.
|
* use a shift instead.
|
||||||
*/
|
*/
|
||||||
switch ( blit->format ) {
|
switch ( tex->format ) {
|
||||||
case RADEON_TXF_32BPP_ARGB8888:
|
case RADEON_TXFORMAT_ARGB8888:
|
||||||
case RADEON_TXF_32BPP_RGBA8888:
|
case RADEON_TXFORMAT_RGBA8888:
|
||||||
format = RADEON_COLOR_FORMAT_ARGB8888;
|
format = RADEON_COLOR_FORMAT_ARGB8888;
|
||||||
dword_shift = 0;
|
tex_width = tex->width * 4;
|
||||||
|
blit_width = image->width * 4;
|
||||||
break;
|
break;
|
||||||
case RADEON_TXF_16BPP_AI88:
|
case RADEON_TXFORMAT_AI88:
|
||||||
case RADEON_TXF_16BPP_ARGB1555:
|
case RADEON_TXFORMAT_ARGB1555:
|
||||||
case RADEON_TXF_16BPP_RGB565:
|
case RADEON_TXFORMAT_RGB565:
|
||||||
case RADEON_TXF_16BPP_ARGB4444:
|
case RADEON_TXFORMAT_ARGB4444:
|
||||||
format = RADEON_COLOR_FORMAT_RGB565;
|
format = RADEON_COLOR_FORMAT_RGB565;
|
||||||
dword_shift = 1;
|
tex_width = tex->width * 2;
|
||||||
|
blit_width = image->width * 2;
|
||||||
break;
|
break;
|
||||||
case RADEON_TXF_8BPP_I:
|
case RADEON_TXFORMAT_I8:
|
||||||
case RADEON_TXF_8BPP_RGB332:
|
case RADEON_TXFORMAT_RGB332:
|
||||||
format = RADEON_COLOR_FORMAT_CI8;
|
format = RADEON_COLOR_FORMAT_CI8;
|
||||||
dword_shift = 2;
|
tex_width = tex->width * 1;
|
||||||
|
blit_width = image->width * 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DRM_ERROR( "invalid blit format %d\n", blit->format );
|
DRM_ERROR( "invalid texture format %d\n", tex->format );
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DRM_DEBUG( " tex=%dx%d blit=%d\n",
|
||||||
|
tex_width, tex->height, blit_width );
|
||||||
|
|
||||||
/* Flush the pixel cache. This ensures no pixel data gets mixed
|
/* Flush the pixel cache. This ensures no pixel data gets mixed
|
||||||
* up with the texture data from the host data blit, otherwise
|
* up with the texture data from the host data blit, otherwise
|
||||||
* part of the texture image may be corrupted.
|
* part of the texture image may be corrupted.
|
||||||
|
@ -1026,46 +1032,88 @@ static int radeon_cp_dispatch_blit( drm_device_t *dev,
|
||||||
|
|
||||||
ADVANCE_RING();
|
ADVANCE_RING();
|
||||||
|
|
||||||
|
/* Make a copy of the parameters in case we have to update them
|
||||||
|
* for a multi-pass texture blit.
|
||||||
|
*/
|
||||||
|
y = image->y;
|
||||||
|
height = image->height;
|
||||||
|
data = (u8 *)image->data;
|
||||||
|
|
||||||
|
size = height * blit_width;
|
||||||
|
|
||||||
|
if ( size > RADEON_MAX_TEXTURE_SIZE ) {
|
||||||
|
/* Texture image is too large, do a multipass upload */
|
||||||
|
ret = -EAGAIN;
|
||||||
|
|
||||||
|
/* Adjust the blit size to fit the indirect buffer */
|
||||||
|
height = RADEON_MAX_TEXTURE_SIZE / blit_width;
|
||||||
|
size = height * blit_width;
|
||||||
|
|
||||||
|
/* Update the input parameters for next time */
|
||||||
|
image->y += height;
|
||||||
|
image->height -= height;
|
||||||
|
image->data = (char *)image->data + size;
|
||||||
|
|
||||||
|
if ( copy_to_user( tex->image, image, sizeof(*image) ) ) {
|
||||||
|
DRM_ERROR( "EFAULT on tex->image\n" );
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
} else if ( size < 4 ) {
|
||||||
|
size = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
dwords = size / 4;
|
||||||
|
|
||||||
/* Dispatch the indirect buffer.
|
/* Dispatch the indirect buffer.
|
||||||
*/
|
*/
|
||||||
buf = dma->buflist[blit->idx];
|
buffer = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
|
||||||
buf_priv = buf->dev_private;
|
|
||||||
|
|
||||||
if ( buf->pid != current->pid ) {
|
buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 );
|
||||||
DRM_ERROR( "process %d using buffer owned by %d\n",
|
buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
|
||||||
current->pid, buf->pid );
|
RADEON_GMC_BRUSH_NONE |
|
||||||
return -EINVAL;
|
(format << 8) |
|
||||||
}
|
RADEON_GMC_SRC_DATATYPE_COLOR |
|
||||||
if ( buf->pending ) {
|
RADEON_ROP3_S |
|
||||||
DRM_ERROR( "sending pending buffer %d\n", blit->idx );
|
RADEON_DP_SRC_SOURCE_HOST_DATA |
|
||||||
return -EINVAL;
|
RADEON_GMC_CLR_CMP_CNTL_DIS |
|
||||||
|
RADEON_GMC_WR_MSK_DIS);
|
||||||
|
|
||||||
|
buffer[2] = (tex->pitch << 22) | (tex->offset >> 10);
|
||||||
|
buffer[3] = 0xffffffff;
|
||||||
|
buffer[4] = 0xffffffff;
|
||||||
|
buffer[5] = (y << 16) | image->x;
|
||||||
|
buffer[6] = (height << 16) | image->width;
|
||||||
|
buffer[7] = dwords;
|
||||||
|
|
||||||
|
buffer += 8;
|
||||||
|
|
||||||
|
if ( tex_width >= 32 ) {
|
||||||
|
/* Texture image width is larger than the minimum, so we
|
||||||
|
* can upload it directly.
|
||||||
|
*/
|
||||||
|
if ( copy_from_user( buffer, data, dwords * sizeof(u32) ) ) {
|
||||||
|
DRM_ERROR( "EFAULT on data, %d dwords\n", dwords );
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Texture image width is less than the minimum, so we
|
||||||
|
* need to pad out each image scanline to the minimum
|
||||||
|
* width.
|
||||||
|
*/
|
||||||
|
for ( i = 0 ; i < tex->height ; i++ ) {
|
||||||
|
if ( copy_from_user( buffer, data, tex_width ) ) {
|
||||||
|
DRM_ERROR( "EFAULT on pad, %d bytes\n",
|
||||||
|
tex_width );
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
buffer += 8;
|
||||||
|
data += tex_width;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buf_priv->discard = 1;
|
buf->pid = current->pid;
|
||||||
|
|
||||||
dwords = (blit->width * blit->height) >> dword_shift;
|
|
||||||
if ( !dwords ) dwords = 1;
|
|
||||||
|
|
||||||
data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
|
|
||||||
|
|
||||||
data[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 );
|
|
||||||
data[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
|
|
||||||
RADEON_GMC_BRUSH_NONE |
|
|
||||||
(format << 8) |
|
|
||||||
RADEON_GMC_SRC_DATATYPE_COLOR |
|
|
||||||
RADEON_ROP3_S |
|
|
||||||
RADEON_DP_SRC_SOURCE_HOST_DATA |
|
|
||||||
RADEON_GMC_CLR_CMP_CNTL_DIS |
|
|
||||||
RADEON_GMC_WR_MSK_DIS);
|
|
||||||
|
|
||||||
data[2] = (blit->pitch << 22) | (blit->offset >> 10);
|
|
||||||
data[3] = 0xffffffff;
|
|
||||||
data[4] = 0xffffffff;
|
|
||||||
data[5] = (blit->y << 16) | blit->x;
|
|
||||||
data[6] = (blit->height << 16) | blit->width;
|
|
||||||
data[7] = dwords;
|
|
||||||
|
|
||||||
buf->used = (dwords + 8) * sizeof(u32);
|
buf->used = (dwords + 8) * sizeof(u32);
|
||||||
|
buf_priv->discard = 1;
|
||||||
|
|
||||||
radeon_cp_dispatch_indirect( dev, buf, 0, buf->used );
|
radeon_cp_dispatch_indirect( dev, buf, 0, buf->used );
|
||||||
|
|
||||||
|
@ -1080,7 +1128,7 @@ static int radeon_cp_dispatch_blit( drm_device_t *dev,
|
||||||
|
|
||||||
ADVANCE_RING();
|
ADVANCE_RING();
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple )
|
static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple )
|
||||||
|
@ -1090,8 +1138,6 @@ static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple )
|
||||||
RING_LOCALS;
|
RING_LOCALS;
|
||||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
radeon_update_ring_snapshot( dev_priv );
|
|
||||||
|
|
||||||
BEGIN_RING( 35 );
|
BEGIN_RING( 35 );
|
||||||
|
|
||||||
OUT_RING( CP_PACKET0( RADEON_RE_STIPPLE_ADDR, 0 ) );
|
OUT_RING( CP_PACKET0( RADEON_RE_STIPPLE_ADDR, 0 ) );
|
||||||
|
@ -1118,22 +1164,25 @@ int radeon_cp_clear( struct inode *inode, struct file *filp,
|
||||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||||
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||||
drm_radeon_clear_t clear;
|
drm_radeon_clear_t clear;
|
||||||
|
drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
|
||||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
|
LOCK_TEST_WITH_RETURN( dev );
|
||||||
dev->lock.pid != current->pid ) {
|
|
||||||
DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( copy_from_user( &clear, (drm_radeon_clear_t *) arg,
|
if ( copy_from_user( &clear, (drm_radeon_clear_t *)arg,
|
||||||
sizeof(clear) ) )
|
sizeof(clear) ) )
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
|
RING_SPACE_TEST_WITH_RETURN( dev_priv );
|
||||||
|
|
||||||
if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
|
if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
|
||||||
sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
|
sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
|
||||||
|
|
||||||
radeon_cp_dispatch_clear( dev, &clear );
|
if ( copy_from_user( &depth_boxes, clear.depth_boxes,
|
||||||
|
sarea_priv->nbox * sizeof(depth_boxes[0]) ) )
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
radeon_cp_dispatch_clear( dev, &clear, depth_boxes );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1147,11 +1196,9 @@ int radeon_cp_swap( struct inode *inode, struct file *filp,
|
||||||
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||||
|
|
||||||
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
|
LOCK_TEST_WITH_RETURN( dev );
|
||||||
dev->lock.pid != current->pid ) {
|
|
||||||
DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
|
RING_SPACE_TEST_WITH_RETURN( dev_priv );
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
|
if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
|
||||||
sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
|
sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
|
||||||
|
@ -1178,13 +1225,10 @@ int radeon_cp_vertex( struct inode *inode, struct file *filp,
|
||||||
drm_radeon_buf_priv_t *buf_priv;
|
drm_radeon_buf_priv_t *buf_priv;
|
||||||
drm_radeon_vertex_t vertex;
|
drm_radeon_vertex_t vertex;
|
||||||
|
|
||||||
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
|
LOCK_TEST_WITH_RETURN( dev );
|
||||||
dev->lock.pid != current->pid ) {
|
|
||||||
DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
|
if ( !dev_priv ) {
|
||||||
return -EINVAL;
|
DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
|
||||||
}
|
|
||||||
if ( !dev_priv || dev_priv->is_pci ) {
|
|
||||||
DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1207,7 +1251,8 @@ int radeon_cp_vertex( struct inode *inode, struct file *filp,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
VB_AGE_CHECK_WITH_RET( dev_priv );
|
RING_SPACE_TEST_WITH_RETURN( dev_priv );
|
||||||
|
VB_AGE_TEST_WITH_RETURN( dev_priv );
|
||||||
|
|
||||||
buf = dma->buflist[vertex.idx];
|
buf = dma->buflist[vertex.idx];
|
||||||
buf_priv = buf->dev_private;
|
buf_priv = buf->dev_private;
|
||||||
|
@ -1243,13 +1288,10 @@ int radeon_cp_indices( struct inode *inode, struct file *filp,
|
||||||
drm_radeon_indices_t elts;
|
drm_radeon_indices_t elts;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
|
LOCK_TEST_WITH_RETURN( dev );
|
||||||
dev->lock.pid != current->pid ) {
|
|
||||||
DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
|
if ( !dev_priv ) {
|
||||||
return -EINVAL;
|
DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
|
||||||
}
|
|
||||||
if ( !dev_priv || dev_priv->is_pci ) {
|
|
||||||
DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1272,7 +1314,8 @@ int radeon_cp_indices( struct inode *inode, struct file *filp,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
VB_AGE_CHECK_WITH_RET( dev_priv );
|
RING_SPACE_TEST_WITH_RETURN( dev_priv );
|
||||||
|
VB_AGE_TEST_WITH_RETURN( dev_priv );
|
||||||
|
|
||||||
buf = dma->buflist[elts.idx];
|
buf = dma->buflist[elts.idx];
|
||||||
buf_priv = buf->dev_private;
|
buf_priv = buf->dev_private;
|
||||||
|
@ -1308,37 +1351,34 @@ int radeon_cp_indices( struct inode *inode, struct file *filp,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int radeon_cp_blit( struct inode *inode, struct file *filp,
|
int radeon_cp_texture( struct inode *inode, struct file *filp,
|
||||||
unsigned int cmd, unsigned long arg )
|
unsigned int cmd, unsigned long arg )
|
||||||
{
|
{
|
||||||
drm_file_t *priv = filp->private_data;
|
drm_file_t *priv = filp->private_data;
|
||||||
drm_device_t *dev = priv->dev;
|
drm_device_t *dev = priv->dev;
|
||||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||||
drm_device_dma_t *dma = dev->dma;
|
drm_radeon_texture_t tex;
|
||||||
drm_radeon_blit_t blit;
|
drm_radeon_tex_image_t image;
|
||||||
|
|
||||||
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
|
LOCK_TEST_WITH_RETURN( dev );
|
||||||
dev->lock.pid != current->pid ) {
|
|
||||||
DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( copy_from_user( &blit, (drm_radeon_blit_t *)arg,
|
if ( copy_from_user( &tex, (drm_radeon_texture_t *)arg, sizeof(tex) ) )
|
||||||
sizeof(blit) ) )
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
DRM_DEBUG( "%s: pid=%d index=%d\n",
|
if ( tex.image == NULL ) {
|
||||||
__FUNCTION__, current->pid, blit.idx );
|
DRM_ERROR( "null texture image!\n" );
|
||||||
|
|
||||||
if ( blit.idx < 0 || blit.idx > dma->buf_count ) {
|
|
||||||
DRM_ERROR( "sending %d buffers (of %d max)\n",
|
|
||||||
blit.idx, dma->buf_count );
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
VB_AGE_CHECK_WITH_RET( dev_priv );
|
if ( copy_from_user( &image,
|
||||||
|
(drm_radeon_tex_image_t *)tex.image,
|
||||||
|
sizeof(image) ) )
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
return radeon_cp_dispatch_blit( dev, &blit );
|
RING_SPACE_TEST_WITH_RETURN( dev_priv );
|
||||||
|
VB_AGE_TEST_WITH_RETURN( dev_priv );
|
||||||
|
|
||||||
|
return radeon_cp_dispatch_texture( dev, &tex, &image );
|
||||||
}
|
}
|
||||||
|
|
||||||
int radeon_cp_stipple( struct inode *inode, struct file *filp,
|
int radeon_cp_stipple( struct inode *inode, struct file *filp,
|
||||||
|
@ -1346,23 +1386,21 @@ int radeon_cp_stipple( struct inode *inode, struct file *filp,
|
||||||
{
|
{
|
||||||
drm_file_t *priv = filp->private_data;
|
drm_file_t *priv = filp->private_data;
|
||||||
drm_device_t *dev = priv->dev;
|
drm_device_t *dev = priv->dev;
|
||||||
|
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||||
drm_radeon_stipple_t stipple;
|
drm_radeon_stipple_t stipple;
|
||||||
u32 mask[32];
|
u32 mask[32];
|
||||||
|
|
||||||
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
|
LOCK_TEST_WITH_RETURN( dev );
|
||||||
dev->lock.pid != current->pid ) {
|
|
||||||
DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( copy_from_user( &stipple, (drm_radeon_stipple_t *)arg,
|
if ( copy_from_user( &stipple, (drm_radeon_stipple_t *)arg,
|
||||||
sizeof(stipple) ) )
|
sizeof(stipple) ) )
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
if ( copy_from_user( &mask, stipple.mask,
|
if ( copy_from_user( &mask, stipple.mask, 32 * sizeof(u32) ) )
|
||||||
32 * sizeof(u32) ) )
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
|
RING_SPACE_TEST_WITH_RETURN( dev_priv );
|
||||||
|
|
||||||
radeon_cp_dispatch_stipple( dev, mask );
|
radeon_cp_dispatch_stipple( dev, mask );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1380,13 +1418,10 @@ int radeon_cp_indirect( struct inode *inode, struct file *filp,
|
||||||
drm_radeon_indirect_t indirect;
|
drm_radeon_indirect_t indirect;
|
||||||
RING_LOCALS;
|
RING_LOCALS;
|
||||||
|
|
||||||
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
|
LOCK_TEST_WITH_RETURN( dev );
|
||||||
dev->lock.pid != current->pid ) {
|
|
||||||
DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
|
if ( !dev_priv ) {
|
||||||
return -EINVAL;
|
DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
|
||||||
}
|
|
||||||
if ( !dev_priv || dev_priv->is_pci ) {
|
|
||||||
DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1423,7 +1458,8 @@ int radeon_cp_indirect( struct inode *inode, struct file *filp,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
VB_AGE_CHECK_WITH_RET( dev_priv );
|
RING_SPACE_TEST_WITH_RETURN( dev_priv );
|
||||||
|
VB_AGE_TEST_WITH_RETURN( dev_priv );
|
||||||
|
|
||||||
buf->used = indirect.end;
|
buf->used = indirect.end;
|
||||||
buf_priv->discard = indirect.discard;
|
buf_priv->discard = indirect.discard;
|
||||||
|
|
|
@ -126,10 +126,11 @@ typedef struct drm_control {
|
||||||
} drm_control_t;
|
} drm_control_t;
|
||||||
|
|
||||||
typedef enum drm_map_type {
|
typedef enum drm_map_type {
|
||||||
_DRM_FRAME_BUFFER = 0, /* WC (no caching), no core dump */
|
_DRM_FRAME_BUFFER = 0, /* WC (no caching), no core dump */
|
||||||
_DRM_REGISTERS = 1, /* no caching, no core dump */
|
_DRM_REGISTERS = 1, /* no caching, no core dump */
|
||||||
_DRM_SHM = 2, /* shared, cached */
|
_DRM_SHM = 2, /* shared, cached */
|
||||||
_DRM_AGP = 3 /* AGP/GART */
|
_DRM_AGP = 3, /* AGP/GART */
|
||||||
|
_DRM_SCATTER_GATHER = 4 /* Scatter/gather memory for PCI DMA */
|
||||||
} drm_map_type_t;
|
} drm_map_type_t;
|
||||||
|
|
||||||
typedef enum drm_map_flags {
|
typedef enum drm_map_flags {
|
||||||
|
@ -238,7 +239,8 @@ typedef struct drm_buf_desc {
|
||||||
int high_mark; /* High water mark */
|
int high_mark; /* High water mark */
|
||||||
enum {
|
enum {
|
||||||
_DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA */
|
_DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA */
|
||||||
_DRM_AGP_BUFFER = 0x02 /* Buffer is in agp space */
|
_DRM_AGP_BUFFER = 0x02, /* Buffer is in agp space */
|
||||||
|
_DRM_SG_BUFFER = 0x04 /* Scatter/gather memory buffer */
|
||||||
} flags;
|
} flags;
|
||||||
unsigned long agp_start; /* Start address of where the agp buffers
|
unsigned long agp_start; /* Start address of where the agp buffers
|
||||||
* are in the agp aperture */
|
* are in the agp aperture */
|
||||||
|
@ -344,6 +346,11 @@ typedef struct drm_agp_info {
|
||||||
unsigned short id_device;
|
unsigned short id_device;
|
||||||
} drm_agp_info_t;
|
} drm_agp_info_t;
|
||||||
|
|
||||||
|
typedef struct drm_scatter_gather {
|
||||||
|
unsigned long size; /* In bytes -- will round to page boundary */
|
||||||
|
unsigned long handle; /* Used for mapping / unmapping */
|
||||||
|
} drm_scatter_gather_t;
|
||||||
|
|
||||||
#define DRM_IOCTL_BASE 'd'
|
#define DRM_IOCTL_BASE 'd'
|
||||||
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
|
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
|
||||||
#define DRM_IOR(nr,size) _IOR(DRM_IOCTL_BASE,nr,size)
|
#define DRM_IOR(nr,size) _IOR(DRM_IOCTL_BASE,nr,size)
|
||||||
|
@ -399,6 +406,9 @@ typedef struct drm_agp_info {
|
||||||
#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t)
|
#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t)
|
||||||
#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t)
|
#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t)
|
||||||
|
|
||||||
|
#define DRM_IOCTL_SG_ALLOC DRM_IOW( 0x38, drm_scatter_gather_t)
|
||||||
|
#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, drm_scatter_gather_t)
|
||||||
|
|
||||||
/* MGA specific ioctls */
|
/* MGA specific ioctls */
|
||||||
#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t)
|
#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t)
|
||||||
#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x41, drm_lock_t)
|
#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x41, drm_lock_t)
|
||||||
|
|
20
shared/drm.h
20
shared/drm.h
|
@ -126,10 +126,11 @@ typedef struct drm_control {
|
||||||
} drm_control_t;
|
} drm_control_t;
|
||||||
|
|
||||||
typedef enum drm_map_type {
|
typedef enum drm_map_type {
|
||||||
_DRM_FRAME_BUFFER = 0, /* WC (no caching), no core dump */
|
_DRM_FRAME_BUFFER = 0, /* WC (no caching), no core dump */
|
||||||
_DRM_REGISTERS = 1, /* no caching, no core dump */
|
_DRM_REGISTERS = 1, /* no caching, no core dump */
|
||||||
_DRM_SHM = 2, /* shared, cached */
|
_DRM_SHM = 2, /* shared, cached */
|
||||||
_DRM_AGP = 3 /* AGP/GART */
|
_DRM_AGP = 3, /* AGP/GART */
|
||||||
|
_DRM_SCATTER_GATHER = 4 /* Scatter/gather memory for PCI DMA */
|
||||||
} drm_map_type_t;
|
} drm_map_type_t;
|
||||||
|
|
||||||
typedef enum drm_map_flags {
|
typedef enum drm_map_flags {
|
||||||
|
@ -238,7 +239,8 @@ typedef struct drm_buf_desc {
|
||||||
int high_mark; /* High water mark */
|
int high_mark; /* High water mark */
|
||||||
enum {
|
enum {
|
||||||
_DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA */
|
_DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA */
|
||||||
_DRM_AGP_BUFFER = 0x02 /* Buffer is in agp space */
|
_DRM_AGP_BUFFER = 0x02, /* Buffer is in agp space */
|
||||||
|
_DRM_SG_BUFFER = 0x04 /* Scatter/gather memory buffer */
|
||||||
} flags;
|
} flags;
|
||||||
unsigned long agp_start; /* Start address of where the agp buffers
|
unsigned long agp_start; /* Start address of where the agp buffers
|
||||||
* are in the agp aperture */
|
* are in the agp aperture */
|
||||||
|
@ -344,6 +346,11 @@ typedef struct drm_agp_info {
|
||||||
unsigned short id_device;
|
unsigned short id_device;
|
||||||
} drm_agp_info_t;
|
} drm_agp_info_t;
|
||||||
|
|
||||||
|
typedef struct drm_scatter_gather {
|
||||||
|
unsigned long size; /* In bytes -- will round to page boundary */
|
||||||
|
unsigned long handle; /* Used for mapping / unmapping */
|
||||||
|
} drm_scatter_gather_t;
|
||||||
|
|
||||||
#define DRM_IOCTL_BASE 'd'
|
#define DRM_IOCTL_BASE 'd'
|
||||||
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
|
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
|
||||||
#define DRM_IOR(nr,size) _IOR(DRM_IOCTL_BASE,nr,size)
|
#define DRM_IOR(nr,size) _IOR(DRM_IOCTL_BASE,nr,size)
|
||||||
|
@ -399,6 +406,9 @@ typedef struct drm_agp_info {
|
||||||
#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t)
|
#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t)
|
||||||
#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t)
|
#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t)
|
||||||
|
|
||||||
|
#define DRM_IOCTL_SG_ALLOC DRM_IOW( 0x38, drm_scatter_gather_t)
|
||||||
|
#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, drm_scatter_gather_t)
|
||||||
|
|
||||||
/* MGA specific ioctls */
|
/* MGA specific ioctls */
|
||||||
#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t)
|
#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t)
|
||||||
#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x41, drm_lock_t)
|
#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x41, drm_lock_t)
|
||||||
|
|
Loading…
Reference in New Issue