Update DRM from DRI CVS as of today. Notable changes include Radeon

suspend/resume support and Rage 128 pageflipping support (both of which require
XFree86 from CVS), along with miscellaneous cleanups.
This commit is contained in:
Eric Anholt 2003-08-19 02:57:31 +00:00
parent f09e4e876e
commit 7a0f4bee0d
35 changed files with 1060 additions and 682 deletions

View File

@ -86,6 +86,8 @@ int DRM(ati_pcigart_init)( drm_device_t *dev,
}
}
DRM_MEMORYBARRIER();
ret = 1;
done:

View File

@ -45,7 +45,7 @@
#define DRM_IOC_WRITE _IOC_WRITE
#define DRM_IOC_READWRITE _IOC_READ|_IOC_WRITE
#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
#elif defined(__FreeBSD__) || defined(__NetBSD__)
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#if defined(__FreeBSD__) && defined(XFree86Server)
/* Prevent name collision when including sys/ioccom.h */
#undef ioctl

View File

@ -27,6 +27,7 @@
* Authors:
* Rickard E. (Rik) Faith <faith@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
* $FreeBSD$
*/
@ -101,13 +102,13 @@ typedef struct drm_file drm_file_t;
#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
/* Mapping helper macros */
#define DRM_IOREMAP(map) \
#define DRM_IOREMAP(map, dev) \
(map)->handle = DRM(ioremap)( dev, map )
#define DRM_IOREMAP_NOCACHE(map) \
#define DRM_IOREMAP_NOCACHE(map, dev) \
(map)->handle = DRM(ioremap_nocache)( dev, map )
#define DRM_IOREMAPFREE(map) \
#define DRM_IOREMAPFREE(map, dev) \
do { \
if ( (map)->handle && (map)->size ) \
DRM(ioremapfree)( map ); \
@ -196,7 +197,8 @@ typedef struct drm_buf_entry {
drm_buf_t *buflist;
int seg_count;
int page_order;
unsigned long *seglist;
vm_offset_t *seglist;
dma_addr_t *seglist_bus;
drm_freelist_t freelist;
} drm_buf_entry_t;
@ -402,11 +404,8 @@ extern void DRM(mem_uninit)(void);
extern void *DRM(alloc)(size_t size, int area);
extern void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size,
int area);
extern char *DRM(strdup)(const char *s, int area);
extern void DRM(strfree)(char *s, int area);
extern void DRM(free)(void *pt, size_t size, int area);
extern void *DRM(ioremap)(drm_device_t *dev, drm_local_map_t *map);
extern void *DRM(ioremap_nocache)(drm_device_t *dev, drm_local_map_t *map);
extern void DRM(ioremapfree)(drm_local_map_t *map);
#if __REALLY_HAVE_AGP
@ -448,7 +447,7 @@ extern void DRM(reclaim_buffers)(drm_device_t *dev, DRMFILE filp);
#if __HAVE_DMA_IRQ
extern int DRM(irq_install)( drm_device_t *dev, int irq );
extern int DRM(irq_uninstall)( drm_device_t *dev );
extern void DRM(dma_service)( DRM_IRQ_ARGS );
extern irqreturn_t DRM(dma_service)( DRM_IRQ_ARGS );
extern void DRM(driver_irq_preinstall)( drm_device_t *dev );
extern void DRM(driver_irq_postinstall)( drm_device_t *dev );
extern void DRM(driver_irq_uninstall)( drm_device_t *dev );
@ -565,6 +564,12 @@ extern int DRM(sg_alloc)(DRM_IOCTL_ARGS);
extern int DRM(sg_free)(DRM_IOCTL_ARGS);
#endif
/* consistent PCI memory functions (drm_pci.h) */
extern void *DRM(pci_alloc)(drm_device_t *dev, size_t size,
size_t align, dma_addr_t maxaddr,
dma_addr_t *busaddr);
extern void DRM(pci_free)(drm_device_t *dev, size_t size,
void *vaddr, dma_addr_t busaddr);
#endif /* __KERNEL__ */
#endif /* _DRM_P_H_ */

View File

@ -27,6 +27,7 @@
* Author:
* Rickard E. (Rik) Faith <faith@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
* $FreeBSD$
*/
@ -255,25 +256,6 @@ drm_agp_head_t *DRM(agp_init)(void)
head->agpdev = agpdev;
agp_get_info(agpdev, &head->info);
head->memory = NULL;
#if 0 /* bogus */
switch (head->agp_info.chipset) {
case INTEL_GENERIC: head->chipset = "Intel"; break;
case INTEL_LX: head->chipset = "Intel 440LX"; break;
case INTEL_BX: head->chipset = "Intel 440BX"; break;
case INTEL_GX: head->chipset = "Intel 440GX"; break;
case INTEL_I810: head->chipset = "Intel i810"; break;
case VIA_GENERIC: head->chipset = "VIA"; break;
case VIA_VP3: head->chipset = "VIA VP3"; break;
case VIA_MVP3: head->chipset = "VIA MVP3"; break;
case VIA_APOLLO_PRO: head->chipset = "VIA Apollo Pro"; break;
case SIS_GENERIC: head->chipset = "SiS"; break;
case AMD_GENERIC: head->chipset = "AMD"; break;
case AMD_IRONGATE: head->chipset = "AMD Irongate"; break;
case ALI_GENERIC: head->chipset = "ALi"; break;
case ALI_M1541: head->chipset = "ALi M1541"; break;
default:
}
#endif
DRM_INFO("AGP at 0x%08lx %dMB\n",
(long)head->info.ai_aperture_base,
(int)(head->info.ai_aperture_size >> 20));

View File

@ -27,6 +27,7 @@
* Authors:
* Rickard E. (Rik) Faith <faith@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
* $FreeBSD$
*/

View File

@ -27,6 +27,7 @@
* Authors:
* Rickard E. (Rik) Faith <faith@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
* $FreeBSD$
*/
@ -136,12 +137,12 @@ int DRM(addmap)( DRM_IOCTL_ARGS )
#endif
}
#endif /* __REALLY_HAVE_MTRR */
DRM_IOREMAP(map);
DRM_IOREMAP(map, dev);
break;
case _DRM_SHM:
map->handle = (void *)DRM(alloc)(map->size, DRM_MEM_SAREA);
DRM_DEBUG( "%ld %d %p\n",
DRM_DEBUG( "%lu %d %p\n",
map->size, DRM(order)( map->size ), map->handle );
if ( !map->handle ) {
DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
@ -279,31 +280,33 @@ int DRM(rmmap)( DRM_IOCTL_ARGS )
#if __HAVE_DMA
static void DRM(cleanup_buf_error)(drm_buf_entry_t *entry)
static void DRM(cleanup_buf_error)(drm_device_t *dev, drm_buf_entry_t *entry)
{
int i;
#if __HAVE_PCI_DMA
if (entry->seg_count) {
for (i = 0; i < entry->seg_count; i++) {
DRM(free)((void *)entry->seglist[i],
entry->buf_size,
DRM_MEM_DMA);
if (entry->seglist[i] != NULL)
DRM(pci_free)(dev, entry->buf_size,
(void *)entry->seglist[i],
entry->seglist_bus[i]);
}
DRM(free)(entry->seglist,
entry->seg_count *
sizeof(*entry->seglist),
DRM_MEM_SEGS);
DRM(free)(entry->seglist_bus, entry->seg_count *
sizeof(*entry->seglist_bus), DRM_MEM_SEGS);
entry->seg_count = 0;
}
#endif /* __HAVE_PCI_DMA */
if(entry->buf_count) {
for(i = 0; i < entry->buf_count; i++) {
if(entry->buflist[i].dev_private) {
DRM(free)(entry->buflist[i].dev_private,
entry->buflist[i].dev_priv_size,
DRM_MEM_BUFS);
}
if (entry->buf_count) {
for (i = 0; i < entry->buf_count; i++) {
DRM(free)(entry->buflist[i].dev_private,
entry->buflist[i].dev_priv_size, DRM_MEM_BUFS);
}
DRM(free)(entry->buflist,
entry->buf_count *
@ -395,7 +398,9 @@ static int DRM(addbufs_agp)(drm_device_t *dev, drm_buf_desc_t *request)
if(!buf->dev_private) {
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
DRM(cleanup_buf_error)(entry);
DRM(cleanup_buf_error)(dev, entry);
DRM_UNLOCK;
return DRM_ERR(ENOMEM);
}
memset( buf->dev_private, 0, buf->dev_priv_size );
@ -413,7 +418,7 @@ static int DRM(addbufs_agp)(drm_device_t *dev, drm_buf_desc_t *request)
DRM_MEM_BUFS );
if(!temp_buflist) {
/* Free the entry because it isn't valid */
DRM(cleanup_buf_error)(entry);
DRM(cleanup_buf_error)(dev, entry);
DRM_UNLOCK;
return DRM_ERR(ENOMEM);
}
@ -450,7 +455,7 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
int total;
int page_order;
drm_buf_entry_t *entry;
unsigned long page;
vm_offset_t vaddr;
drm_buf_t *buf;
int alignment;
unsigned long offset;
@ -459,6 +464,7 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
int page_count;
unsigned long *temp_pagelist;
drm_buf_t **temp_buflist;
dma_addr_t bus_addr;
count = request->count;
order = DRM(order)(request->size);
@ -482,42 +488,37 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
return DRM_ERR(ENOMEM); /* May only call once for each order */
}
entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist),
DRM_MEM_BUFS );
if ( !entry->buflist ) {
DRM_UNLOCK;
return DRM_ERR(ENOMEM);
}
memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
entry->buflist = DRM(alloc)(count * sizeof(*entry->buflist),
DRM_MEM_BUFS);
entry->seglist = DRM(alloc)(count * sizeof(*entry->seglist),
DRM_MEM_SEGS);
entry->seglist_bus = DRM(alloc)(count * sizeof(*entry->seglist_bus),
DRM_MEM_SEGS);
entry->seglist = DRM(alloc)( count * sizeof(*entry->seglist),
DRM_MEM_SEGS );
if ( !entry->seglist ) {
DRM(free)( entry->buflist,
count * sizeof(*entry->buflist),
DRM_MEM_BUFS );
DRM_UNLOCK;
return DRM_ERR(ENOMEM);
}
memset( entry->seglist, 0, count * sizeof(*entry->seglist) );
/* Keep the original pagelist until we know all the allocations
* have succeeded
*/
temp_pagelist = DRM(alloc)((dma->page_count + (count << page_order)) *
sizeof(*dma->pagelist), DRM_MEM_PAGES);
temp_pagelist = DRM(realloc)( dma->pagelist,
dma->page_count * sizeof(*dma->pagelist),
(dma->page_count + (count << page_order))
* sizeof(*dma->pagelist),
DRM_MEM_PAGES );
if(!temp_pagelist) {
DRM(free)( entry->buflist,
count * sizeof(*entry->buflist),
DRM_MEM_BUFS );
DRM(free)( entry->seglist,
count * sizeof(*entry->seglist),
DRM_MEM_SEGS );
if (entry->buflist == NULL || entry->seglist == NULL ||
temp_pagelist == NULL) {
DRM(free)(entry->buflist, count * sizeof(*entry->buflist),
DRM_MEM_BUFS);
DRM(free)(entry->seglist, count * sizeof(*entry->seglist),
DRM_MEM_SEGS);
DRM(free)(entry->seglist_bus, count *
sizeof(*entry->seglist_bus), DRM_MEM_SEGS);
DRM_UNLOCK;
return DRM_ERR(ENOMEM);
}
dma->pagelist = temp_pagelist;
bzero(entry->buflist, count * sizeof(*entry->buflist));
bzero(entry->seglist, count * sizeof(*entry->seglist));
memcpy(temp_pagelist, dma->pagelist, dma->page_count *
sizeof(*dma->pagelist));
DRM_DEBUG( "pagelist: %d entries\n",
dma->page_count + (count << page_order) );
@ -527,15 +528,28 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
page_count = 0;
while ( entry->buf_count < count ) {
page = (unsigned long)DRM(alloc)( size, DRM_MEM_DMA );
if ( !page ) break;
entry->seglist[entry->seg_count++] = page;
vaddr = (vm_offset_t) DRM(pci_alloc)(dev, size, alignment,
0xfffffffful, &bus_addr);
if (vaddr == NULL) {
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
entry->seg_count = count;
DRM(cleanup_buf_error)(dev, entry);
DRM(free)(temp_pagelist, (dma->page_count +
(count << page_order)) * sizeof(*dma->pagelist),
DRM_MEM_PAGES);
DRM_UNLOCK;
return DRM_ERR(ENOMEM);
}
entry->seglist_bus[entry->seg_count] = bus_addr;
entry->seglist[entry->seg_count++] = vaddr;
for ( i = 0 ; i < (1 << page_order) ; i++ ) {
DRM_DEBUG( "page %d @ 0x%08lx\n",
dma->page_count + page_count,
page + PAGE_SIZE * i );
dma->pagelist[dma->page_count + page_count++]
= page + PAGE_SIZE * i;
(long)vaddr + PAGE_SIZE * i );
temp_pagelist[dma->page_count + page_count++] =
vaddr + PAGE_SIZE * i;
}
for ( offset = 0 ;
offset + size <= total && entry->buf_count < count ;
@ -546,10 +560,28 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
buf->order = order;
buf->used = 0;
buf->offset = (dma->byte_count + byte_count + offset);
buf->address = (void *)(page + offset);
buf->address = (void *)(vaddr + offset);
buf->bus_address = bus_addr + offset;
buf->next = NULL;
buf->pending = 0;
buf->filp = NULL;
buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T);
buf->dev_private = DRM(alloc)(sizeof(DRIVER_BUF_PRIV_T),
DRM_MEM_BUFS);
if (buf->dev_private == NULL) {
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
entry->seg_count = count;
DRM(cleanup_buf_error)(dev, entry);
DRM(free)(temp_pagelist, (dma->page_count +
(count << page_order)) *
sizeof(*dma->pagelist), DRM_MEM_PAGES );
DRM_UNLOCK;
return DRM_ERR(ENOMEM);
}
bzero(buf->dev_private, buf->dev_priv_size);
DRM_DEBUG( "buffer %d @ %p\n",
entry->buf_count, buf->address );
}
@ -561,9 +593,12 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
(dma->buf_count + entry->buf_count)
* sizeof(*dma->buflist),
DRM_MEM_BUFS );
if(!temp_buflist) {
if (temp_buflist == NULL) {
/* Free the entry because it isn't valid */
DRM(cleanup_buf_error)(entry);
DRM(cleanup_buf_error)(dev, entry);
DRM(free)(temp_pagelist, (dma->page_count +
(count << page_order)) * sizeof(*dma->pagelist),
DRM_MEM_PAGES);
DRM_UNLOCK;
return DRM_ERR(ENOMEM);
}
@ -573,6 +608,13 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
dma->buflist[i + dma->buf_count] = &entry->buflist[i];
}
/* No allocations failed, so now we can replace the orginal pagelist
* with the new one.
*/
DRM(free)(dma->pagelist, dma->page_count * sizeof(*dma->pagelist),
DRM_MEM_PAGES);
dma->pagelist = temp_pagelist;
dma->buf_count += entry->buf_count;
dma->seg_count += entry->seg_count;
dma->page_count += entry->seg_count << page_order;
@ -669,7 +711,7 @@ static int DRM(addbufs_sg)(drm_device_t *dev, drm_buf_desc_t *request)
if(!buf->dev_private) {
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
DRM(cleanup_buf_error)(entry);
DRM(cleanup_buf_error)(dev, entry);
DRM_UNLOCK;
return DRM_ERR(ENOMEM);
}
@ -693,7 +735,7 @@ static int DRM(addbufs_sg)(drm_device_t *dev, drm_buf_desc_t *request)
DRM_MEM_BUFS );
if(!temp_buflist) {
/* Free the entry because it isn't valid */
DRM(cleanup_buf_error)(entry);
DRM(cleanup_buf_error)(dev, entry);
DRM_UNLOCK;
return DRM_ERR(ENOMEM);
}

View File

@ -27,6 +27,7 @@
* Authors:
* Rickard E. (Rik) Faith <faith@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
* $FreeBSD$
*/

View File

@ -70,6 +70,7 @@ void DRM(dma_takedown)(drm_device_t *dev)
/* Clear dma buffers */
for (i = 0; i <= DRM_MAX_ORDER; i++) {
#if __HAVE_PCI_DMA
if (dma->bufs[i].seg_count) {
DRM_DEBUG("order %d: buf_count = %d,"
" seg_count = %d\n",
@ -77,22 +78,27 @@ void DRM(dma_takedown)(drm_device_t *dev)
dma->bufs[i].buf_count,
dma->bufs[i].seg_count);
for (j = 0; j < dma->bufs[i].seg_count; j++) {
DRM(free)((void *)dma->bufs[i].seglist[j],
dma->bufs[i].buf_size,
DRM_MEM_DMA);
if (dma->bufs[i].seglist[j] != NULL)
DRM(pci_free)(dev, dma->bufs[i].buf_size,
(void *)dma->bufs[i].seglist[j],
dma->bufs[i].seglist_bus[j]);
}
DRM(free)(dma->bufs[i].seglist,
dma->bufs[i].seg_count
* sizeof(*dma->bufs[0].seglist),
DRM_MEM_SEGS);
DRM(free)(dma->bufs[i].seglist_bus,
dma->bufs[i].seg_count
* sizeof(*dma->bufs[0].seglist_bus),
DRM_MEM_SEGS);
}
if(dma->bufs[i].buf_count) {
for(j = 0; j < dma->bufs[i].buf_count; j++) {
if(dma->bufs[i].buflist[j].dev_private) {
DRM(free)(dma->bufs[i].buflist[j].dev_private,
#endif /* __HAVE_PCI_DMA */
if (dma->bufs[i].buf_count) {
for (j = 0; j < dma->bufs[i].buf_count; j++) {
DRM(free)(dma->bufs[i].buflist[j].dev_private,
dma->bufs[i].buflist[j].dev_priv_size,
DRM_MEM_BUFS);
}
}
DRM(free)(dma->bufs[i].buflist,
dma->bufs[i].buf_count *
@ -101,17 +107,10 @@ void DRM(dma_takedown)(drm_device_t *dev)
}
}
if (dma->buflist) {
DRM(free)(dma->buflist,
dma->buf_count * sizeof(*dma->buflist),
DRM_MEM_BUFS);
}
if (dma->pagelist) {
DRM(free)(dma->pagelist,
dma->page_count * sizeof(*dma->pagelist),
DRM_MEM_PAGES);
}
DRM(free)(dma->buflist, dma->buf_count * sizeof(*dma->buflist),
DRM_MEM_BUFS);
DRM(free)(dma->pagelist, dma->page_count * sizeof(*dma->pagelist),
DRM_MEM_PAGES);
DRM(free)(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
dev->dma = NULL;
}
@ -161,6 +160,9 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
if ( !irq )
return DRM_ERR(EINVAL);
if (dev->dev_private == NULL)
return DRM_ERR(EINVAL);
DRM_LOCK;
if ( dev->irq ) {
DRM_UNLOCK;
@ -215,7 +217,7 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
if ( retcode ) {
#elif defined(__NetBSD__)
dev->irqh = pci_intr_establish(&dev->pa.pa_pc, dev->ih, IPL_TTY,
(int (*)(DRM_IRQ_ARGS))DRM(dma_service), dev);
(irqreturn_t (*)(DRM_IRQ_ARGS))DRM(dma_service), dev);
if ( !dev->irqh ) {
#endif
DRM_LOCK;

View File

@ -567,7 +567,7 @@ static int DRM(takedown)( drm_device_t *dev )
mrdesc.mr_base = map->offset;
mrdesc.mr_len = map->size;
mrdesc.mr_flags = MDF_WRITECOMBINE;
act = MEMRANGE_SET_UPDATE;
act = MEMRANGE_SET_REMOVE;
bcopy(DRIVER_NAME, &mrdesc.mr_owner, strlen(DRIVER_NAME));
retcode = mem_range_attr_set(&mrdesc, &act);
map->mtrr=1;

View File

@ -36,408 +36,89 @@
#if defined(__FreeBSD__) || defined(__NetBSD__)
#define malloctype DRM(M_DRM)
/* The macros conflicted in the MALLOC_DEFINE */
MALLOC_DEFINE(malloctype, "drm", "DRM Data Structures");
#undef malloctype
#endif
typedef struct drm_mem_stats {
const char *name;
int succeed_count;
int free_count;
int fail_count;
unsigned long bytes_allocated;
unsigned long bytes_freed;
} drm_mem_stats_t;
static DRM_SPINTYPE DRM(mem_lock);
static unsigned long DRM(ram_available) = 0; /* In pages */
static unsigned long DRM(ram_used) = 0;
static drm_mem_stats_t DRM(mem_stats)[] = {
[DRM_MEM_DMA] = { "dmabufs" },
[DRM_MEM_SAREA] = { "sareas" },
[DRM_MEM_DRIVER] = { "driver" },
[DRM_MEM_MAGIC] = { "magic" },
[DRM_MEM_IOCTLS] = { "ioctltab" },
[DRM_MEM_MAPS] = { "maplist" },
[DRM_MEM_BUFS] = { "buflist" },
[DRM_MEM_SEGS] = { "seglist" },
[DRM_MEM_PAGES] = { "pagelist" },
[DRM_MEM_FILES] = { "files" },
[DRM_MEM_QUEUES] = { "queues" },
[DRM_MEM_CMDS] = { "commands" },
[DRM_MEM_MAPPINGS] = { "mappings" },
[DRM_MEM_BUFLISTS] = { "buflists" },
[DRM_MEM_AGPLISTS] = { "agplist" },
[DRM_MEM_SGLISTS] = { "sglist" },
[DRM_MEM_TOTALAGP] = { "totalagp" },
[DRM_MEM_BOUNDAGP] = { "boundagp" },
[DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
[DRM_MEM_STUB] = { "stub" },
{ NULL, 0, } /* Last entry must be null */
};
#ifdef DEBUG_MEMORY
#include "drm_memory_debug.h"
#else
void DRM(mem_init)(void)
{
drm_mem_stats_t *mem;
#ifdef __NetBSD__
malloc_type_attach(DRM(M_DRM));
#endif
DRM_SPININIT(DRM(mem_lock), "drm memory");
for (mem = DRM(mem_stats); mem->name; ++mem) {
mem->succeed_count = 0;
mem->free_count = 0;
mem->fail_count = 0;
mem->bytes_allocated = 0;
mem->bytes_freed = 0;
}
DRM(ram_available) = 0; /* si.totalram */
DRM(ram_used) = 0;
}
void DRM(mem_uninit)(void)
{
DRM_SPINUNINIT(DRM(mem_lock));
}
#ifdef __FreeBSD__
/* drm_mem_info is called whenever a process reads /dev/drm/mem. */
static int
DRM(_mem_info)(drm_mem_stats_t *stats, struct sysctl_oid *oidp, void *arg1,
int arg2, struct sysctl_req *req)
{
drm_mem_stats_t *pt;
char buf[128];
int error;
DRM_SYSCTL_PRINT(" total counts "
" | outstanding \n");
DRM_SYSCTL_PRINT("type alloc freed fail bytes freed"
" | allocs bytes\n\n");
DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu |\n",
"system", 0, 0, 0, DRM(ram_available));
DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu |\n",
"locked", 0, 0, 0, DRM(ram_used));
DRM_SYSCTL_PRINT("\n");
for (pt = stats; pt->name; pt++) {
DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n",
pt->name,
pt->succeed_count,
pt->free_count,
pt->fail_count,
pt->bytes_allocated,
pt->bytes_freed,
pt->succeed_count - pt->free_count,
(long)pt->bytes_allocated
- (long)pt->bytes_freed);
}
SYSCTL_OUT(req, "", 1);
return 0;
}
int DRM(mem_info) DRM_SYSCTL_HANDLER_ARGS
{
int ret;
drm_mem_stats_t *stats;
stats = malloc(sizeof(DRM(mem_stats)), DRM(M_DRM), M_NOWAIT);
if (stats == NULL)
return ENOMEM;
DRM_SPINLOCK(&DRM(mem_lock));
bcopy(DRM(mem_stats), stats, sizeof(DRM(mem_stats)));
DRM_SPINUNLOCK(&DRM(mem_lock));
ret = DRM(_mem_info)(stats, oidp, arg1, arg2, req);
free(stats, DRM(M_DRM));
return ret;
}
#endif /* __FreeBSD__ */
void *DRM(alloc)(size_t size, int area)
{
void *pt;
if (!size) {
DRM_MEM_ERROR(area, "Allocating 0 bytes\n");
return NULL;
}
if (!(pt = malloc(size, DRM(M_DRM), M_NOWAIT))) {
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[area].fail_count;
DRM_SPINUNLOCK(&DRM(mem_lock));
return NULL;
}
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[area].succeed_count;
DRM(mem_stats)[area].bytes_allocated += size;
DRM_SPINUNLOCK(&DRM(mem_lock));
return pt;
return malloc(size, DRM(M_DRM), M_NOWAIT);
}
void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size, int area)
{
void *pt;
if (!(pt = DRM(alloc)(size, area))) return NULL;
pt = malloc(size, DRM(M_DRM), M_NOWAIT);
if (pt == NULL)
return NULL;
if (oldpt && oldsize) {
memcpy(pt, oldpt, oldsize);
DRM(free)(oldpt, oldsize, area);
free(oldpt, DRM(M_DRM));
}
return pt;
}
char *DRM(strdup)(const char *s, int area)
{
char *pt;
int length = s ? strlen(s) : 0;
if (!(pt = DRM(alloc)(length+1, area))) return NULL;
strcpy(pt, s);
return pt;
}
void DRM(strfree)(char *s, int area)
{
unsigned int size;
if (!s) return;
size = 1 + strlen(s);
DRM(free)((void *)s, size, area);
}
void DRM(free)(void *pt, size_t size, int area)
{
int alloc_count;
int free_count;
if (!pt)
DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n");
else
free(pt, DRM(M_DRM));
DRM_SPINLOCK(&DRM(mem_lock));
DRM(mem_stats)[area].bytes_freed += size;
free_count = ++DRM(mem_stats)[area].free_count;
alloc_count = DRM(mem_stats)[area].succeed_count;
DRM_SPINUNLOCK(&DRM(mem_lock));
if (free_count > alloc_count) {
DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n",
free_count, alloc_count);
}
free(pt, DRM(M_DRM));
}
void *DRM(ioremap)( drm_device_t *dev, drm_local_map_t *map )
{
void *pt;
if (!map->size) {
DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
"Mapping 0 bytes at 0x%08lx\n", map->offset);
return NULL;
}
#ifdef __NetBSD__
map->iot = dev->pa.pa_memt;
#endif
#ifdef __FreeBSD__
if (!(pt = pmap_mapdev(map->offset, map->size))) {
return pmap_mapdev(map->offset, map->size);
#elif defined(__NetBSD__)
map->iot = dev->pa.pa_memt;
if (bus_space_map(map->iot, map->offset, map->size,
BUS_SPACE_MAP_LINEAR, &map->ioh)) {
#endif
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count;
DRM_SPINUNLOCK(&DRM(mem_lock));
BUS_SPACE_MAP_LINEAR, &map->ioh))
return NULL;
}
#ifdef __NetBSD__
pt = bus_space_vaddr(map->iot, map->ioh);
return bus_space_vaddr(map->iot, map->ioh);
#endif
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += map->size;
DRM_SPINUNLOCK(&DRM(mem_lock));
return pt;
}
/* unused so far */
#if 0
void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size)
{
void *pt;
if (!size) {
DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
"Mapping 0 bytes at 0x%08lx\n", offset);
return NULL;
}
/* FIXME FOR BSD */
if (!(pt = ioremap_nocache(offset, size))) {
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count;
DRM_SPINUNLOCK(&DRM(mem_lock));
return NULL;
}
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size;
DRM_SPINUNLOCK(&DRM(mem_lock));
return pt;
}
#endif
void DRM(ioremapfree)(drm_local_map_t *map)
{
int alloc_count;
int free_count;
if (map->handle == NULL)
DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
"Attempt to free NULL pointer\n");
else
#ifdef __FreeBSD__
pmap_unmapdev((vm_offset_t) map->handle, map->size);
pmap_unmapdev((vm_offset_t) map->handle, map->size);
#elif defined(__NetBSD__)
bus_space_unmap(map->iot, map->ioh, map->size);
bus_space_unmap(map->iot, map->ioh, map->size);
#endif
DRM_SPINLOCK(&DRM(mem_lock));
DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += map->size;
free_count = ++DRM(mem_stats)[DRM_MEM_MAPPINGS].free_count;
alloc_count = DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
DRM_SPINUNLOCK(&DRM(mem_lock));
if (free_count > alloc_count) {
DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
"Excess frees: %d frees, %d allocs\n",
free_count, alloc_count);
}
}
#if __REALLY_HAVE_AGP
agp_memory *DRM(alloc_agp)(int pages, u32 type)
{
agp_memory *handle;
if (!pages) {
DRM_MEM_ERROR(DRM_MEM_TOTALAGP, "Allocating 0 pages\n");
return NULL;
}
if ((handle = DRM(agp_allocate_memory)(pages, type))) {
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_allocated
+= pages << PAGE_SHIFT;
DRM_SPINUNLOCK(&DRM(mem_lock));
return handle;
}
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_TOTALAGP].fail_count;
DRM_SPINUNLOCK(&DRM(mem_lock));
return NULL;
return DRM(agp_allocate_memory)(pages, type);
}
int DRM(free_agp)(agp_memory *handle, int pages)
{
int alloc_count;
int free_count;
if (!handle) {
DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
"Attempt to free NULL AGP handle\n");
return DRM_ERR(EINVAL);
}
if (DRM(agp_free_memory)(handle)) {
DRM_SPINLOCK(&DRM(mem_lock));
free_count = ++DRM(mem_stats)[DRM_MEM_TOTALAGP].free_count;
alloc_count = DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_freed
+= pages << PAGE_SHIFT;
DRM_SPINUNLOCK(&DRM(mem_lock));
if (free_count > alloc_count) {
DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
"Excess frees: %d frees, %d allocs\n",
free_count, alloc_count);
}
return 0;
}
return DRM_ERR(EINVAL);
return DRM(agp_free_memory)(handle);
}
int DRM(bind_agp)(agp_memory *handle, unsigned int start)
{
int retcode;
device_t dev = DRM_AGP_FIND_DEVICE();
struct agp_memory_info info;
if (!dev)
return EINVAL;
if (!handle) {
DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
"Attempt to bind NULL AGP handle\n");
return DRM_ERR(EINVAL);
}
if (!(retcode = DRM(agp_bind_memory)(handle, start))) {
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
agp_memory_info(dev, handle, &info);
DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_allocated
+= info.ami_size;
DRM_SPINUNLOCK(&DRM(mem_lock));
return DRM_ERR(0);
}
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_BOUNDAGP].fail_count;
DRM_SPINUNLOCK(&DRM(mem_lock));
return DRM_ERR(retcode);
return DRM(agp_bind_memory)(handle, start);
}
int DRM(unbind_agp)(agp_memory *handle)
{
int alloc_count;
int free_count;
int retcode = EINVAL;
device_t dev = DRM_AGP_FIND_DEVICE();
struct agp_memory_info info;
if (!dev)
return EINVAL;
if (!handle) {
DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
"Attempt to unbind NULL AGP handle\n");
return DRM_ERR(retcode);
}
agp_memory_info(dev, handle, &info);
if ((retcode = DRM(agp_unbind_memory)(handle)))
return DRM_ERR(retcode);
DRM_SPINLOCK(&DRM(mem_lock));
free_count = ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].free_count;
alloc_count = DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_freed
+= info.ami_size;
DRM_SPINUNLOCK(&DRM(mem_lock));
if (free_count > alloc_count) {
DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
"Excess frees: %d frees, %d allocs\n",
free_count, alloc_count);
}
return DRM_ERR(retcode);
return DRM(agp_unbind_memory)(handle);
}
#endif
#endif /* __REALLY_HAVE_AGP */
#endif /* DEBUG_MEMORY */

View File

@ -0,0 +1,413 @@
/* drm_memory.h -- Memory management wrappers for DRM -*- linux-c -*-
* Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* 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
* VA LINUX SYSTEMS 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:
* Rickard E. (Rik) Faith <faith@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
* $FreeBSD$
*/
#include "drmP.h"
typedef struct drm_mem_stats {
const char *name;
int succeed_count;
int free_count;
int fail_count;
unsigned long bytes_allocated;
unsigned long bytes_freed;
} drm_mem_stats_t;
static DRM_SPINTYPE DRM(mem_lock);
static unsigned long DRM(ram_available) = 0; /* In pages */
static unsigned long DRM(ram_used) = 0;
static drm_mem_stats_t DRM(mem_stats)[] = {
[DRM_MEM_DMA] = { "dmabufs" },
[DRM_MEM_SAREA] = { "sareas" },
[DRM_MEM_DRIVER] = { "driver" },
[DRM_MEM_MAGIC] = { "magic" },
[DRM_MEM_IOCTLS] = { "ioctltab" },
[DRM_MEM_MAPS] = { "maplist" },
[DRM_MEM_BUFS] = { "buflist" },
[DRM_MEM_SEGS] = { "seglist" },
[DRM_MEM_PAGES] = { "pagelist" },
[DRM_MEM_FILES] = { "files" },
[DRM_MEM_QUEUES] = { "queues" },
[DRM_MEM_CMDS] = { "commands" },
[DRM_MEM_MAPPINGS] = { "mappings" },
[DRM_MEM_BUFLISTS] = { "buflists" },
[DRM_MEM_AGPLISTS] = { "agplist" },
[DRM_MEM_SGLISTS] = { "sglist" },
[DRM_MEM_TOTALAGP] = { "totalagp" },
[DRM_MEM_BOUNDAGP] = { "boundagp" },
[DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
[DRM_MEM_STUB] = { "stub" },
{ NULL, 0, } /* Last entry must be null */
};
void DRM(mem_init)(void)
{
drm_mem_stats_t *mem;
#ifdef __NetBSD__
malloc_type_attach(DRM(M_DRM));
#endif
DRM_SPININIT(DRM(mem_lock), "drm memory");
for (mem = DRM(mem_stats); mem->name; ++mem) {
mem->succeed_count = 0;
mem->free_count = 0;
mem->fail_count = 0;
mem->bytes_allocated = 0;
mem->bytes_freed = 0;
}
DRM(ram_available) = 0; /* si.totalram */
DRM(ram_used) = 0;
}
void DRM(mem_uninit)(void)
{
DRM_SPINUNINIT(DRM(mem_lock));
}
#ifdef __FreeBSD__
/* drm_mem_info is called whenever a process reads /dev/drm/mem. */
static int
DRM(_mem_info)(drm_mem_stats_t *stats, struct sysctl_oid *oidp, void *arg1,
int arg2, struct sysctl_req *req)
{
drm_mem_stats_t *pt;
char buf[128];
int error;
DRM_SYSCTL_PRINT(" total counts "
" | outstanding \n");
DRM_SYSCTL_PRINT("type alloc freed fail bytes freed"
" | allocs bytes\n\n");
DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu |\n",
"system", 0, 0, 0, DRM(ram_available));
DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu |\n",
"locked", 0, 0, 0, DRM(ram_used));
DRM_SYSCTL_PRINT("\n");
for (pt = stats; pt->name; pt++) {
DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n",
pt->name,
pt->succeed_count,
pt->free_count,
pt->fail_count,
pt->bytes_allocated,
pt->bytes_freed,
pt->succeed_count - pt->free_count,
(long)pt->bytes_allocated
- (long)pt->bytes_freed);
}
SYSCTL_OUT(req, "", 1);
return 0;
}
int DRM(mem_info) DRM_SYSCTL_HANDLER_ARGS
{
int ret;
drm_mem_stats_t *stats;
stats = malloc(sizeof(DRM(mem_stats)), DRM(M_DRM), M_NOWAIT);
if (stats == NULL)
return ENOMEM;
DRM_SPINLOCK(&DRM(mem_lock));
bcopy(DRM(mem_stats), stats, sizeof(DRM(mem_stats)));
DRM_SPINUNLOCK(&DRM(mem_lock));
ret = DRM(_mem_info)(stats, oidp, arg1, arg2, req);
free(stats, DRM(M_DRM));
return ret;
}
#endif /* __FreeBSD__ */
void *DRM(alloc)(size_t size, int area)
{
void *pt;
if (!size) {
DRM_MEM_ERROR(area, "Allocating 0 bytes\n");
return NULL;
}
if (!(pt = malloc(size, DRM(M_DRM), M_NOWAIT))) {
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[area].fail_count;
DRM_SPINUNLOCK(&DRM(mem_lock));
return NULL;
}
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[area].succeed_count;
DRM(mem_stats)[area].bytes_allocated += size;
DRM_SPINUNLOCK(&DRM(mem_lock));
return pt;
}
void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size, int area)
{
void *pt;
if (!(pt = DRM(alloc)(size, area))) return NULL;
if (oldpt && oldsize) {
memcpy(pt, oldpt, oldsize);
DRM(free)(oldpt, oldsize, area);
}
return pt;
}
void DRM(free)(void *pt, size_t size, int area)
{
int alloc_count;
int free_count;
if (pt == NULL)
return;
free(pt, DRM(M_DRM));
DRM_SPINLOCK(&DRM(mem_lock));
DRM(mem_stats)[area].bytes_freed += size;
free_count = ++DRM(mem_stats)[area].free_count;
alloc_count = DRM(mem_stats)[area].succeed_count;
DRM_SPINUNLOCK(&DRM(mem_lock));
if (free_count > alloc_count) {
DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n",
free_count, alloc_count);
}
}
void *DRM(ioremap)( drm_device_t *dev, drm_local_map_t *map )
{
void *pt;
if (!map->size) {
DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
"Mapping 0 bytes at 0x%08lx\n", map->offset);
return NULL;
}
#ifdef __NetBSD__
map->iot = dev->pa.pa_memt;
#endif
#ifdef __FreeBSD__
if (!(pt = pmap_mapdev(map->offset, map->size))) {
#elif defined(__NetBSD__)
if (bus_space_map(map->iot, map->offset, map->size,
BUS_SPACE_MAP_LINEAR, &map->ioh)) {
#endif
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count;
DRM_SPINUNLOCK(&DRM(mem_lock));
return NULL;
}
#ifdef __NetBSD__
pt = bus_space_vaddr(map->iot, map->ioh);
#endif
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += map->size;
DRM_SPINUNLOCK(&DRM(mem_lock));
return pt;
}
/* unused so far */
#if 0
void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size)
{
void *pt;
if (!size) {
DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
"Mapping 0 bytes at 0x%08lx\n", offset);
return NULL;
}
/* FIXME FOR BSD */
if (!(pt = ioremap_nocache(offset, size))) {
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count;
DRM_SPINUNLOCK(&DRM(mem_lock));
return NULL;
}
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size;
DRM_SPINUNLOCK(&DRM(mem_lock));
return pt;
}
#endif
void DRM(ioremapfree)(drm_local_map_t *map)
{
int alloc_count;
int free_count;
if (map->handle == NULL)
DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
"Attempt to free NULL pointer\n");
else
#ifdef __FreeBSD__
pmap_unmapdev((vm_offset_t) map->handle, map->size);
#elif defined(__NetBSD__)
bus_space_unmap(map->iot, map->ioh, map->size);
#endif
DRM_SPINLOCK(&DRM(mem_lock));
DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += map->size;
free_count = ++DRM(mem_stats)[DRM_MEM_MAPPINGS].free_count;
alloc_count = DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
DRM_SPINUNLOCK(&DRM(mem_lock));
if (free_count > alloc_count) {
DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
"Excess frees: %d frees, %d allocs\n",
free_count, alloc_count);
}
}
#if __REALLY_HAVE_AGP
agp_memory *DRM(alloc_agp)(int pages, u32 type)
{
agp_memory *handle;
if (!pages) {
DRM_MEM_ERROR(DRM_MEM_TOTALAGP, "Allocating 0 pages\n");
return NULL;
}
if ((handle = DRM(agp_allocate_memory)(pages, type))) {
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_allocated
+= pages << PAGE_SHIFT;
DRM_SPINUNLOCK(&DRM(mem_lock));
return handle;
}
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_TOTALAGP].fail_count;
DRM_SPINUNLOCK(&DRM(mem_lock));
return NULL;
}
int DRM(free_agp)(agp_memory *handle, int pages)
{
int alloc_count;
int free_count;
if (!handle) {
DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
"Attempt to free NULL AGP handle\n");
return DRM_ERR(EINVAL);
}
if (DRM(agp_free_memory)(handle)) {
DRM_SPINLOCK(&DRM(mem_lock));
free_count = ++DRM(mem_stats)[DRM_MEM_TOTALAGP].free_count;
alloc_count = DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_freed
+= pages << PAGE_SHIFT;
DRM_SPINUNLOCK(&DRM(mem_lock));
if (free_count > alloc_count) {
DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
"Excess frees: %d frees, %d allocs\n",
free_count, alloc_count);
}
return 0;
}
return DRM_ERR(EINVAL);
}
int DRM(bind_agp)(agp_memory *handle, unsigned int start)
{
int retcode;
device_t dev = DRM_AGP_FIND_DEVICE();
struct agp_memory_info info;
if (!dev)
return EINVAL;
if (!handle) {
DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
"Attempt to bind NULL AGP handle\n");
return DRM_ERR(EINVAL);
}
if (!(retcode = DRM(agp_bind_memory)(handle, start))) {
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
agp_memory_info(dev, handle, &info);
DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_allocated
+= info.ami_size;
DRM_SPINUNLOCK(&DRM(mem_lock));
return DRM_ERR(0);
}
DRM_SPINLOCK(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_BOUNDAGP].fail_count;
DRM_SPINUNLOCK(&DRM(mem_lock));
return DRM_ERR(retcode);
}
int DRM(unbind_agp)(agp_memory *handle)
{
int alloc_count;
int free_count;
int retcode = EINVAL;
device_t dev = DRM_AGP_FIND_DEVICE();
struct agp_memory_info info;
if (!dev)
return EINVAL;
if (!handle) {
DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
"Attempt to unbind NULL AGP handle\n");
return DRM_ERR(retcode);
}
agp_memory_info(dev, handle, &info);
if ((retcode = DRM(agp_unbind_memory)(handle)))
return DRM_ERR(retcode);
DRM_SPINLOCK(&DRM(mem_lock));
free_count = ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].free_count;
alloc_count = DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_freed
+= info.ami_size;
DRM_SPINUNLOCK(&DRM(mem_lock));
if (free_count > alloc_count) {
DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
"Excess frees: %d frees, %d allocs\n",
free_count, alloc_count);
}
return DRM_ERR(retcode);
}
#endif

View File

@ -1,6 +1,36 @@
/**
* \file drm_os_freebsd.h
* OS-specific #defines for FreeBSD
*
* \author Eric Anholt <anholt@FreeBSD.org>
*/
/*
* Copyright 2003 Eric Anholt
* 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
* VA LINUX SYSTEMS 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.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/malloc.h>
@ -27,6 +57,7 @@
#include <machine/pmap.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/endian.h>
#include <sys/mman.h>
#include <sys/rman.h>
#include <sys/memrange.h>
@ -111,10 +142,12 @@
#define DRM_SUSER(p) suser(p)
#define DRM_TASKQUEUE_ARGS void *arg, int pending
#define DRM_IRQ_ARGS void *arg
typedef void irqreturn_t;
#define IRQ_HANDLED /* nothing */
#define IRQ_NONE /* nothing */
#define DRM_DEVICE drm_device_t *dev = kdev->si_drv1
#define DRM_MALLOC(size) malloc( size, DRM(M_DRM), M_NOWAIT )
#define DRM_FREE(pt,size) free( pt, DRM(M_DRM) )
#define DRM_VTOPHYS(addr) vtophys(addr)
/* Read/write from bus space, with byteswapping to le if necessary */
#define DRM_READ8(map, offset) *(volatile u_int8_t *) (((unsigned long)(map)->handle) + (offset))
@ -206,10 +239,21 @@ while (!condition) { \
#define DRM_GET_USER_UNCHECKED(val, uaddr) \
((val) = fuword(uaddr), 0)
#define DRM_WRITEMEMORYBARRIER( map ) \
bus_space_barrier((map)->iot, (map)->ioh, 0, (map)->size, 0);
#define DRM_READMEMORYBARRIER( map ) \
bus_space_barrier((map)->iot, (map)->ioh, 0, (map)->size, BUS_SPACE_BARRIER_READ);
/* DRM_READMEMORYBARRIER() prevents reordering of reads.
* DRM_WRITEMEMORYBARRIER() prevents reordering of writes.
* DRM_MEMORYBARRIER() prevents reordering of reads and writes.
*/
#if defined(__i386__)
#define DRM_READMEMORYBARRIER() __asm __volatile( \
"lock; addl $0,0(%%esp)" : : : "memory");
#define DRM_WRITEMEMORYBARRIER() __asm __volatile("" : : : "memory");
#define DRM_MEMORYBARRIER() __asm __volatile( \
"lock; addl $0,0(%%esp)" : : : "memory");
#elif defined(__alpha__)
#define DRM_READMEMORYBARRIER() alpha_mb();
#define DRM_WRITEMEMORYBARRIER() alpha_wmb();
#define DRM_MEMORYBARRIER() alpha_mb();
#endif
#define PAGE_ALIGN(addr) round_page(addr)
@ -230,7 +274,8 @@ typedef struct drm_chipinfo
char *name;
} drm_chipinfo_t;
#define cpu_to_le32(x) (x) /* FIXME */
#define cpu_to_le32(x) htole32(x)
#define le32_to_cpu(x) le32toh(x)
typedef unsigned long dma_addr_t;
typedef u_int32_t atomic_t;
@ -356,14 +401,11 @@ find_first_zero_bit(volatile void *p, int max)
#endif
#define DRM_SYSCTL_PRINT(fmt, arg...) \
do { \
snprintf(buf, sizeof(buf), fmt, ##arg); \
error = SYSCTL_OUT(req, buf, strlen(buf)); \
if (error) return error;
#define DRM_SYSCTL_PRINT_RET(ret, fmt, arg...) \
snprintf(buf, sizeof(buf), fmt, ##arg); \
error = SYSCTL_OUT(req, buf, strlen(buf)); \
if (error) { ret; return error; }
if (error) return error; \
} while (0)
#define DRM_FIND_MAP(dest, o) \
@ -396,5 +438,7 @@ extern drm_file_t *DRM(find_file_by_proc)(drm_device_t *dev,
extern int DRM(sysctl_init)(drm_device_t *dev);
extern int DRM(sysctl_cleanup)(drm_device_t *dev);
/* Memory info sysctl (drm_memory.h) */
/* Memory info sysctl (drm_memory_debug.h) */
#ifdef DEBUG_MEMORY
extern int DRM(mem_info) DRM_SYSCTL_HANDLER_ARGS;
#endif

67
sys/dev/drm/drm_pci.h Normal file
View File

@ -0,0 +1,67 @@
/**
* \file drm_pci.h
* \brief PCI consistent, DMA-accessible memory functions.
*
* \author Eric Anholt <anholt@FreeBSD.org>
*/
/*
* Copyright 2003 Eric Anholt.
* 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 THE
* AUTHOR 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.
*
* $FreeBSD$
*/
#include "dev/drm/drmP.h"
/**********************************************************************/
/** \name PCI memory */
/*@{*/
/**
* \brief Allocate a physically contiguous DMA-accessible consistent
* memory block.
*/
void *
DRM(pci_alloc)(drm_device_t *dev, size_t size, size_t align, dma_addr_t maxaddr,
dma_addr_t *busaddr)
{
void *vaddr;
vaddr = contigmalloc(size, DRM(M_DRM), M_WAITOK, 0ul, maxaddr, align,
0);
*busaddr = vtophys(vaddr);
return vaddr;
}
/**
* \brief Free a DMA-accessible consistent memory block.
*/
void
DRM(pci_free)(drm_device_t *dev, size_t size, void *vaddr, dma_addr_t busaddr)
{
#if __FreeBSD_version > 500000
contigfree(vaddr, size, DRM(M_DRM)); /* Not available on 4.x */
#endif
}
/*@}*/

View File

@ -1,5 +1,11 @@
/* sarea.h -- SAREA definitions -*- linux-c -*-
/**
* \file drm_sarea.h
* \brief SAREA definitions
*
* \author Michel Dänzer <michel@daenzer.net>
*/
/*
* Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
@ -22,23 +28,23 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Michel Dänzer <michel@daenzer.net>
*
* $FreeBSD$
*/
#ifndef _DRM_SAREA_H_
#define _DRM_SAREA_H_
/** Maximum number of drawables in the SAREA */
#define SAREA_MAX_DRAWABLES 256
typedef struct _drm_sarea_drawable_t {
/** SAREA drawable */
typedef struct drm_sarea_drawable {
unsigned int stamp;
unsigned int flags;
} drm_sarea_drawable_t;
typedef struct _dri_sarea_frame_t {
/** SAREA frame */
typedef struct drm_sarea_frame {
unsigned int x;
unsigned int y;
unsigned int width;
@ -46,13 +52,14 @@ typedef struct _dri_sarea_frame_t {
unsigned int fullscreen;
} drm_sarea_frame_t;
typedef struct _drm_sarea_t {
/* first thing is always the drm locking structure */
/** SAREA */
typedef struct drm_sarea {
/** first thing is always the DRM locking structure */
drm_hw_lock_t lock;
/* NOT_DONE: Use readers/writer lock for drawable_lock */
/** \todo Use readers/writer lock for drm_sarea::drawable_lock */
drm_hw_lock_t drawable_lock;
drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES];
drm_sarea_frame_t frame;
drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; /**< drawables */
drm_sarea_frame_t frame; /**< frame */
drm_context_t dummy_context;
} drm_sarea_t;

View File

@ -25,6 +25,7 @@
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Eric Anholt <anholt@FreeBSD.org>
*
* $FreeBSD$
*/

View File

@ -16,7 +16,9 @@ struct DRM(sysctl_list) {
int (*f) DRM_SYSCTL_HANDLER_ARGS;
} DRM(sysctl_list)[] = {
{ "name", DRM(name_info) },
#ifdef DEBUG_MEMORY
{ "mem", DRM(mem_info) },
#endif
{ "vm", DRM(vm_info) },
{ "clients", DRM(clients_info) },
{ "bufs", DRM(bufs_info) },
@ -97,10 +99,10 @@ static int DRM(name_info)DRM_SYSCTL_HANDLER_ARGS
int error;
if (dev->unique) {
DRM_SYSCTL_PRINT("%s 0x%x %s\n",
DRM_SYSCTL_PRINT("%s 0x%x %s",
dev->name, dev2udev(dev->devnode), dev->unique);
} else {
DRM_SYSCTL_PRINT("%s 0x%x\n", dev->name, dev2udev(dev->devnode));
DRM_SYSCTL_PRINT("%s 0x%x", dev->name, dev2udev(dev->devnode));
}
SYSCTL_OUT(req, "", 1);
@ -113,22 +115,22 @@ static int DRM(_vm_info)DRM_SYSCTL_HANDLER_ARGS
drm_device_t *dev = arg1;
drm_local_map_t *map;
drm_map_list_entry_t *listentry;
const char *types[] = { "FB", "REG", "SHM" };
const char *types[] = { "FB", "REG", "SHM", "AGP", "SG" };
const char *type;
int i=0;
char buf[128];
int error;
DRM_SYSCTL_PRINT("slot offset size type flags "
"address mtrr\n\n");
error = SYSCTL_OUT(req, buf, strlen(buf));
if (error) return error;
DRM_SYSCTL_PRINT("\nslot offset size type flags "
"address mtrr\n");
if (dev->maplist != NULL) {
TAILQ_FOREACH(listentry, dev->maplist, link) {
map = listentry->map;
if (map->type < 0 || map->type > 2) type = "??";
else type = types[map->type];
if (map->type < 0 || map->type > 4)
type = "??";
else
type = types[map->type];
DRM_SYSCTL_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ",
i,
map->offset,
@ -137,9 +139,9 @@ static int DRM(_vm_info)DRM_SYSCTL_HANDLER_ARGS
map->flags,
(unsigned long)map->handle);
if (map->mtrr < 0) {
DRM_SYSCTL_PRINT("none\n");
DRM_SYSCTL_PRINT("no\n");
} else {
DRM_SYSCTL_PRINT("%4d\n", map->mtrr);
DRM_SYSCTL_PRINT("yes\n");
}
i++;
}
@ -174,7 +176,7 @@ static int DRM(_bufs_info) DRM_SYSCTL_HANDLER_ARGS
int error;
if (!dma) return 0;
DRM_SYSCTL_PRINT(" o size count free segs pages kB\n\n");
DRM_SYSCTL_PRINT("\n o size count free segs pages kB\n");
for (i = 0; i <= DRM_MAX_ORDER; i++) {
if (dma->bufs[i].buf_count)
DRM_SYSCTL_PRINT("%2d %8d %5d %5d %5d %5d %5d\n",
@ -220,7 +222,7 @@ static int DRM(_clients_info) DRM_SYSCTL_HANDLER_ARGS
char buf[128];
int error;
DRM_SYSCTL_PRINT("a dev pid uid magic ioctls\n\n");
DRM_SYSCTL_PRINT("\na dev pid uid magic ioctls\n");
TAILQ_FOREACH(priv, &dev->files, link) {
DRM_SYSCTL_PRINT("%c %3d %5d %5d %10u %10lu\n",
priv->authenticated ? 'y' : 'n',

View File

@ -74,7 +74,7 @@
/* Driver customization:
*/
#define DRIVER_PRETAKEDOWN() do { \
if ( dev->dev_private ) mga_do_cleanup_dma( dev ); \
mga_do_cleanup_dma( dev ); \
} while (0)
/* DMA customization:

View File

@ -556,9 +556,9 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
(drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle +
init->sarea_priv_offset);
DRM_IOREMAP( dev_priv->warp );
DRM_IOREMAP( dev_priv->primary );
DRM_IOREMAP( dev_priv->buffers );
DRM_IOREMAP( dev_priv->warp, dev );
DRM_IOREMAP( dev_priv->primary, dev );
DRM_IOREMAP( dev_priv->buffers, dev );
if(!dev_priv->warp->handle ||
!dev_priv->primary->handle ||
@ -641,15 +641,23 @@ int mga_do_cleanup_dma( drm_device_t *dev )
{
DRM_DEBUG( "\n" );
#if _HAVE_DMA_IRQ
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
* is freed, it's too late.
*/
if ( dev->irq ) DRM(irq_uninstall)(dev);
#endif
if ( dev->dev_private ) {
drm_mga_private_t *dev_priv = dev->dev_private;
if ( dev_priv->warp != NULL )
DRM_IOREMAPFREE( dev_priv->warp );
DRM_IOREMAPFREE( dev_priv->warp, dev );
if ( dev_priv->primary != NULL )
DRM_IOREMAPFREE( dev_priv->primary );
DRM_IOREMAPFREE( dev_priv->primary, dev );
if ( dev_priv->buffers != NULL )
DRM_IOREMAPFREE( dev_priv->buffers );
DRM_IOREMAPFREE( dev_priv->buffers, dev );
if ( dev_priv->head != NULL ) {
mga_freelist_cleanup( dev );
@ -668,6 +676,8 @@ int mga_dma_init( DRM_IOCTL_ARGS )
DRM_DEVICE;
drm_mga_init_t init;
LOCK_TEST_WITH_RETURN( dev, filp );
DRM_COPY_FROM_USER_IOCTL( init, (drm_mga_init_t *)data, sizeof(init) );
switch ( init.func ) {

View File

@ -133,7 +133,7 @@ extern int mga_getparam( DRM_IOCTL_ARGS );
extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv );
extern int mga_warp_init( drm_mga_private_t *dev_priv );
#define mga_flush_write_combine() DRM_WRITEMEMORYBARRIER(dev_priv->primary)
#define mga_flush_write_combine() DRM_WRITEMEMORYBARRIER()
#if defined(__linux__) && defined(__alpha__)
#define MGA_BASE( reg ) ((unsigned long)(dev_priv->mmio->handle))
@ -144,12 +144,12 @@ extern int mga_warp_init( drm_mga_private_t *dev_priv );
#define MGA_READ( reg ) (_MGA_READ((u32 *)MGA_ADDR(reg)))
#define MGA_READ8( reg ) (_MGA_READ((u8 *)MGA_ADDR(reg)))
#define MGA_WRITE( reg, val ) do { DRM_WRITEMEMORYBARRIER(dev_priv->mmio); MGA_DEREF( reg ) = val; } while (0)
#define MGA_WRITE8( reg, val ) do { DRM_WRITEMEMORYBARRIER(dev_priv->mmio); MGA_DEREF8( reg ) = val; } while (0)
#define MGA_WRITE( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF( reg ) = val; } while (0)
#define MGA_WRITE8( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8( reg ) = val; } while (0)
static inline u32 _MGA_READ(u32 *addr)
{
DRM_READMEMORYBARRIER(dev_priv->mmio);
DRM_MEMORYBARRIER();
return *(volatile u32 *)addr;
}
#else
@ -228,7 +228,7 @@ do { \
if ( MGA_VERBOSE ) { \
DRM_INFO( "BEGIN_DMA( %d ) in %s\n", \
(n), __FUNCTION__ ); \
DRM_INFO( " space=0x%x req=0x%x\n", \
DRM_INFO( " space=0x%x req=0x%Zx\n", \
dev_priv->prim.space, (n) * DMA_BLOCK_SIZE ); \
} \
prim = dev_priv->prim.start; \
@ -278,7 +278,7 @@ do { \
#define DMA_WRITE( offset, val ) \
do { \
if ( MGA_VERBOSE ) { \
DRM_INFO( " DMA_WRITE( 0x%08x ) at 0x%04x\n", \
DRM_INFO( " DMA_WRITE( 0x%08x ) at 0x%04Zx\n", \
(u32)(val), write + (offset) * sizeof(u32) ); \
} \
*(volatile u32 *)(prim + write + (offset) * sizeof(u32)) = val; \

View File

@ -38,7 +38,7 @@
#include "dev/drm/mga_drm.h"
#include "dev/drm/mga_drv.h"
void mga_dma_service( DRM_IRQ_ARGS )
irqreturn_t mga_dma_service( DRM_IRQ_ARGS )
{
drm_device_t *dev = (drm_device_t *) arg;
drm_mga_private_t *dev_priv =
@ -53,7 +53,9 @@ void mga_dma_service( DRM_IRQ_ARGS )
atomic_inc(&dev->vbl_received);
DRM_WAKEUP(&dev->vbl_queue);
DRM(vbl_send_signals)( dev );
return IRQ_HANDLED;
}
return IRQ_NONE;
}
int mga_vblank_wait(drm_device_t *dev, unsigned int *sequence)
@ -95,8 +97,9 @@ void mga_driver_irq_postinstall( drm_device_t *dev ) {
void mga_driver_irq_uninstall( drm_device_t *dev ) {
drm_mga_private_t *dev_priv =
(drm_mga_private_t *)dev->dev_private;
if ( dev_priv ) {
/* Disable *all* interrupts */
MGA_WRITE( MGA_IEN, 0 );
}
if (!dev_priv)
return;
/* Disable *all* interrupts */
MGA_WRITE( MGA_IEN, 0 );
}

View File

@ -29,7 +29,6 @@
* $FreeBSD$
*/
#define __NO_VERSION__
#include "dev/drm/mga.h"
#include "dev/drm/drmP.h"
#include "dev/drm/drm.h"

View File

@ -49,13 +49,18 @@
#define DRIVER_NAME "r128"
#define DRIVER_DESC "ATI Rage 128"
#define DRIVER_DATE "20021029"
#define DRIVER_DATE "20030725"
#define DRIVER_MAJOR 2
#define DRIVER_MINOR 3
#define DRIVER_MINOR 5
#define DRIVER_PATCHLEVEL 0
/* Interface history:
*
* ?? - ??
* 2.4 - Add support for ycbcr textures (no new ioctls)
* 2.5 - Add FLIP ioctl, disable FULLSCREEN.
*/
#define DRIVER_IOCTLS \
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { r128_cce_buffers, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_cce_init, 1, 1 }, \
@ -66,6 +71,7 @@
[DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_engine_reset, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_R128_FULLSCREEN)] = { r128_fullscreen, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_R128_SWAP)] = { r128_cce_swap, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_R128_FLIP)] = { r128_cce_flip, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_R128_CLEAR)] = { r128_cce_clear, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_R128_INDICES)] = { r128_cce_indices, 1, 0 }, \
@ -87,7 +93,7 @@
} while (0)
#define DRIVER_PRETAKEDOWN() do { \
if ( dev->dev_private ) r128_do_cleanup_cce( dev ); \
r128_do_cleanup_cce( dev ); \
} while (0)
/* DMA customization:

View File

@ -83,8 +83,6 @@ static u32 r128_cce_microcode[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
int r128_do_wait_for_idle( drm_r128_private_t *dev_priv );
int R128_READ_PLL(drm_device_t *dev, int addr)
{
drm_r128_private_t *dev_priv = dev->dev_private;
@ -153,7 +151,7 @@ static int r128_do_wait_for_fifo( drm_r128_private_t *dev_priv, int entries )
return DRM_ERR(EBUSY);
}
int r128_do_wait_for_idle( drm_r128_private_t *dev_priv )
static int r128_do_wait_for_idle( drm_r128_private_t *dev_priv )
{
int i, ret;
@ -353,7 +351,7 @@ static void r128_cce_init_ring_buffer( drm_device_t *dev,
R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
entry->busaddr[page_ofs]);
DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
entry->busaddr[page_ofs],
(unsigned long) entry->busaddr[page_ofs],
entry->handle + tmp_ofs );
}
@ -541,10 +539,11 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
(drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
init->sarea_priv_offset);
#if __REALLY_HAVE_AGP
if ( !dev_priv->is_pci ) {
DRM_IOREMAP( dev_priv->cce_ring );
DRM_IOREMAP( dev_priv->ring_rptr );
DRM_IOREMAP( dev_priv->buffers );
DRM_IOREMAP( dev_priv->cce_ring, dev );
DRM_IOREMAP( dev_priv->ring_rptr, dev );
DRM_IOREMAP( dev_priv->buffers, dev );
if(!dev_priv->cce_ring->handle ||
!dev_priv->ring_rptr->handle ||
!dev_priv->buffers->handle) {
@ -553,7 +552,9 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
r128_do_cleanup_cce( dev );
return DRM_ERR(ENOMEM);
}
} else {
} else
#endif
{
dev_priv->cce_ring->handle =
(void *)dev_priv->cce_ring->offset;
dev_priv->ring_rptr->handle =
@ -615,26 +616,34 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
int r128_do_cleanup_cce( drm_device_t *dev )
{
#if _HAVE_DMA_IRQ
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
* is freed, it's too late.
*/
if ( dev->irq ) DRM(irq_uninstall)(dev);
#endif
if ( dev->dev_private ) {
drm_r128_private_t *dev_priv = dev->dev_private;
#if __REALLY_HAVE_SG
#if __REALLY_HAVE_AGP
if ( !dev_priv->is_pci ) {
#endif
if ( dev_priv->cce_ring != NULL )
DRM_IOREMAPFREE( dev_priv->cce_ring );
DRM_IOREMAPFREE( dev_priv->cce_ring, dev );
if ( dev_priv->ring_rptr != NULL )
DRM_IOREMAPFREE( dev_priv->ring_rptr );
DRM_IOREMAPFREE( dev_priv->ring_rptr, dev );
if ( dev_priv->buffers != NULL )
DRM_IOREMAPFREE( dev_priv->buffers );
#if __REALLY_HAVE_SG
} else {
DRM_IOREMAPFREE( dev_priv->buffers, dev );
} else
#endif
{
if (!DRM(ati_pcigart_cleanup)( dev,
dev_priv->phys_pci_gart,
dev_priv->bus_pci_gart ))
DRM_ERROR( "failed to cleanup PCI GART!\n" );
}
#endif
DRM(free)( dev->dev_private, sizeof(drm_r128_private_t),
DRM_MEM_DRIVER );
@ -651,6 +660,8 @@ int r128_cce_init( DRM_IOCTL_ARGS )
DRM_DEBUG( "\n" );
LOCK_TEST_WITH_RETURN( dev, filp );
DRM_COPY_FROM_USER_IOCTL( init, (drm_r128_init_t *)data, sizeof(init) );
switch ( init.func ) {
@ -771,59 +782,8 @@ int r128_engine_reset( DRM_IOCTL_ARGS )
return r128_do_engine_reset( dev );
}
/* ================================================================
* Fullscreen mode
*/
static int r128_do_init_pageflip( drm_device_t *dev )
{
drm_r128_private_t *dev_priv = dev->dev_private;
DRM_DEBUG( "\n" );
dev_priv->crtc_offset = R128_READ( R128_CRTC_OFFSET );
dev_priv->crtc_offset_cntl = R128_READ( R128_CRTC_OFFSET_CNTL );
R128_WRITE( R128_CRTC_OFFSET, dev_priv->front_offset );
R128_WRITE( R128_CRTC_OFFSET_CNTL,
dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL );
dev_priv->page_flipping = 1;
dev_priv->current_page = 0;
return 0;
}
int r128_do_cleanup_pageflip( drm_device_t *dev )
{
drm_r128_private_t *dev_priv = dev->dev_private;
DRM_DEBUG( "\n" );
R128_WRITE( R128_CRTC_OFFSET, dev_priv->crtc_offset );
R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl );
dev_priv->page_flipping = 0;
dev_priv->current_page = 0;
return 0;
}
int r128_fullscreen( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_r128_fullscreen_t fs;
LOCK_TEST_WITH_RETURN( dev, filp );
DRM_COPY_FROM_USER_IOCTL( fs, (drm_r128_fullscreen_t *)data, sizeof(fs) );
switch ( fs.func ) {
case R128_INIT_FULLSCREEN:
return r128_do_init_pageflip( dev );
case R128_CLEANUP_FULLSCREEN:
return r128_do_cleanup_pageflip( dev );
}
return DRM_ERR(EINVAL);
}
@ -916,7 +876,7 @@ drm_buf_t *r128_freelist_get( drm_device_t *dev )
DRM_UDELAY( 1 );
}
DRM_ERROR( "returning NULL!\n" );
DRM_DEBUG( "returning NULL!\n" );
return NULL;
}

View File

@ -164,8 +164,10 @@ typedef struct drm_r128_sarea {
unsigned int last_dispatch;
drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1];
int tex_age[R128_NR_TEX_HEAPS];
unsigned int tex_age[R128_NR_TEX_HEAPS];
int ctx_owner;
int pfAllowPageFlip; /* number of 3d windows (0,1,2 or more) */
int pfCurrentPage; /* which buffer is being displayed? */
} drm_r128_sarea_t;
@ -193,6 +195,7 @@ typedef struct drm_r128_sarea {
#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( 0x50, drm_r128_fullscreen_t)
#define DRM_IOCTL_R128_CLEAR2 DRM_IOW( 0x51, drm_r128_clear2_t)
#define DRM_IOCTL_R128_GETPARAM DRM_IOW( 0x52, drm_r128_getparam_t)
#define DRM_IOCTL_R128_FLIP DRM_IO( 0x53)
typedef struct drm_r128_init {
enum {

View File

@ -75,6 +75,7 @@ drm_chipinfo_t DRM(devicelist)[] = {
#include "dev/drm/drm_ioctl.h"
#include "dev/drm/drm_lock.h"
#include "dev/drm/drm_memory.h"
#include "dev/drm/drm_pci.h"
#include "dev/drm/drm_sysctl.h"
#include "dev/drm/drm_vm.h"
#if __HAVE_SG

View File

@ -149,6 +149,7 @@ extern int r128_do_cleanup_pageflip( drm_device_t *dev );
/* r128_state.c */
extern int r128_cce_clear( DRM_IOCTL_ARGS );
extern int r128_cce_swap( DRM_IOCTL_ARGS );
extern int r128_cce_flip( DRM_IOCTL_ARGS );
extern int r128_cce_vertex( DRM_IOCTL_ARGS );
extern int r128_cce_indices( DRM_IOCTL_ARGS );
extern int r128_cce_blit( DRM_IOCTL_ARGS );
@ -345,13 +346,20 @@ extern int r128_cce_indirect( DRM_IOCTL_ARGS );
#define R128_CCE_VC_CNTL_PRIM_WALK_RING 0x00000030
#define R128_CCE_VC_CNTL_NUM_SHIFT 16
#define R128_DATATYPE_VQ 0
#define R128_DATATYPE_CI4 1
#define R128_DATATYPE_CI8 2
#define R128_DATATYPE_ARGB1555 3
#define R128_DATATYPE_RGB565 4
#define R128_DATATYPE_RGB888 5
#define R128_DATATYPE_ARGB8888 6
#define R128_DATATYPE_RGB332 7
#define R128_DATATYPE_Y8 8
#define R128_DATATYPE_RGB8 9
#define R128_DATATYPE_CI16 10
#define R128_DATATYPE_YVYU422 11
#define R128_DATATYPE_VYUY422 12
#define R128_DATATYPE_AYUV444 14
#define R128_DATATYPE_ARGB4444 15
/* Constants */
@ -442,7 +450,7 @@ do { \
#if defined(__powerpc__)
#define r128_flush_write_combine() (void) GET_RING_HEAD( &dev_priv->ring )
#else
#define r128_flush_write_combine() DRM_WRITEMEMORYBARRIER(dev_priv->ring_rptr)
#define r128_flush_write_combine() DRM_WRITEMEMORYBARRIER()
#endif

View File

@ -38,7 +38,7 @@
#include "dev/drm/r128_drm.h"
#include "dev/drm/r128_drv.h"
void r128_dma_service( DRM_IRQ_ARGS )
irqreturn_t r128_dma_service( DRM_IRQ_ARGS )
{
drm_device_t *dev = (drm_device_t *) arg;
drm_r128_private_t *dev_priv =
@ -53,7 +53,9 @@ void r128_dma_service( DRM_IRQ_ARGS )
atomic_inc(&dev->vbl_received);
DRM_WAKEUP(&dev->vbl_queue);
DRM(vbl_send_signals)( dev );
return IRQ_HANDLED;
}
return IRQ_NONE;
}
int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence)
@ -95,8 +97,9 @@ void r128_driver_irq_postinstall( drm_device_t *dev ) {
void r128_driver_irq_uninstall( drm_device_t *dev ) {
drm_r128_private_t *dev_priv =
(drm_r128_private_t *)dev->dev_private;
if ( dev_priv ) {
/* Disable *all* interrupts */
R128_WRITE( R128_GEN_INT_CNTL, 0 );
}
if (!dev_priv)
return;
/* Disable *all* interrupts */
R128_WRITE( R128_GEN_INT_CNTL, 0 );
}

View File

@ -502,8 +502,16 @@ static void r128_cce_dispatch_swap( drm_device_t *dev )
R128_GMC_AUX_CLIP_DIS |
R128_GMC_WR_MSK_DIS );
OUT_RING( dev_priv->back_pitch_offset_c );
OUT_RING( dev_priv->front_pitch_offset_c );
/* Make this work even if front & back are flipped:
*/
if (dev_priv->current_page == 0) {
OUT_RING( dev_priv->back_pitch_offset_c );
OUT_RING( dev_priv->front_pitch_offset_c );
}
else {
OUT_RING( dev_priv->front_pitch_offset_c );
OUT_RING( dev_priv->back_pitch_offset_c );
}
OUT_RING( (x << 16) | y );
OUT_RING( (x << 16) | y );
@ -530,7 +538,10 @@ static void r128_cce_dispatch_flip( drm_device_t *dev )
{
drm_r128_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
DRM_DEBUG( "page=%d\n", dev_priv->current_page );
DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
__FUNCTION__,
dev_priv->current_page,
dev_priv->sarea_priv->pfCurrentPage);
#if R128_PERFORMANCE_BOXES
/* Do some trivial performance monitoring...
@ -545,10 +556,8 @@ static void r128_cce_dispatch_flip( drm_device_t *dev )
if ( dev_priv->current_page == 0 ) {
OUT_RING( dev_priv->back_offset );
dev_priv->current_page = 1;
} else {
OUT_RING( dev_priv->front_offset );
dev_priv->current_page = 0;
}
ADVANCE_RING();
@ -558,6 +567,8 @@ static void r128_cce_dispatch_flip( drm_device_t *dev )
* performing the swapbuffer ioctl.
*/
dev_priv->sarea_priv->last_frame++;
dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
1 - dev_priv->current_page;
BEGIN_RING( 2 );
@ -804,6 +815,8 @@ static int r128_cce_dispatch_blit( DRMFILE filp,
case R128_DATATYPE_ARGB1555:
case R128_DATATYPE_RGB565:
case R128_DATATYPE_ARGB4444:
case R128_DATATYPE_YVYU422:
case R128_DATATYPE_VYUY422:
dword_shift = 1;
break;
case R128_DATATYPE_CI8:
@ -1266,6 +1279,62 @@ int r128_cce_clear( DRM_IOCTL_ARGS )
return 0;
}
static int r128_do_init_pageflip( drm_device_t *dev )
{
drm_r128_private_t *dev_priv = dev->dev_private;
DRM_DEBUG( "\n" );
dev_priv->crtc_offset = R128_READ( R128_CRTC_OFFSET );
dev_priv->crtc_offset_cntl = R128_READ( R128_CRTC_OFFSET_CNTL );
R128_WRITE( R128_CRTC_OFFSET, dev_priv->front_offset );
R128_WRITE( R128_CRTC_OFFSET_CNTL,
dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL );
dev_priv->page_flipping = 1;
dev_priv->current_page = 0;
dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
return 0;
}
int r128_do_cleanup_pageflip( drm_device_t *dev )
{
drm_r128_private_t *dev_priv = dev->dev_private;
DRM_DEBUG( "\n" );
R128_WRITE( R128_CRTC_OFFSET, dev_priv->crtc_offset );
R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl );
if (dev_priv->current_page != 0)
r128_cce_dispatch_flip( dev );
dev_priv->page_flipping = 0;
return 0;
}
/* Swapping and flipping are different operations, need different ioctls.
* They can & should be intermixed to support multiple 3d windows.
*/
int r128_cce_flip( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
DRM_DEBUG( "%s\n", __FUNCTION__ );
LOCK_TEST_WITH_RETURN( dev, filp );
RING_SPACE_TEST_WITH_RETURN( dev_priv );
if (!dev_priv->page_flipping)
r128_do_init_pageflip( dev );
r128_cce_dispatch_flip( dev );
return 0;
}
int r128_cce_swap( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
@ -1280,13 +1349,9 @@ int r128_cce_swap( DRM_IOCTL_ARGS )
if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
if ( !dev_priv->page_flipping ) {
r128_cce_dispatch_swap( dev );
dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
R128_UPLOAD_MASKS);
} else {
r128_cce_dispatch_flip( dev );
}
r128_cce_dispatch_swap( dev );
dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
R128_UPLOAD_MASKS);
return 0;
}

View File

@ -53,7 +53,7 @@
#define DRIVER_DATE "20020828"
#define DRIVER_MAJOR 1
#define DRIVER_MINOR 8
#define DRIVER_MINOR 9
#define DRIVER_PATCHLEVEL 0
/* Interface history:
@ -81,6 +81,8 @@
* R200_EMIT_PP_CUBIC_OFFSETS_[0..5]. (brian)
* 1.8 - Remove need to call cleanup ioctls on last client exit (keith)
* Add 'GET' queries for starting additional clients on different VT's.
* 1.9 - Add DRM_IOCTL_RADEON_CP_RESUME ioctl.
* Add texture rectangle support for r100.
*/
#define DRIVER_IOCTLS \
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \
@ -89,6 +91,7 @@
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_STOP)] = { radeon_cp_stop, 1, 1 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESET)] = { radeon_cp_reset, 1, 1 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_IDLE)] = { radeon_cp_idle, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESUME)] = { radeon_cp_resume, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_RESET)] = { radeon_engine_reset, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_FULLSCREEN)] = { radeon_fullscreen, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_SWAP)] = { radeon_cp_swap, 1, 0 }, \

View File

@ -906,7 +906,7 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev,
RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
entry->busaddr[page_ofs]);
DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
entry->busaddr[page_ofs],
(unsigned long) entry->busaddr[page_ofs],
entry->handle + tmp_ofs );
}
@ -977,10 +977,36 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev,
RADEON_ISYNC_CPSCRATCH_IDLEGUI) );
}
/* Enable or disable PCI GART on the chip */
static void radeon_set_pcigart( drm_radeon_private_t *dev_priv, int on )
{
u32 tmp = RADEON_READ( RADEON_AIC_CNTL );
if ( on ) {
RADEON_WRITE( RADEON_AIC_CNTL, tmp | RADEON_PCIGART_TRANSLATE_EN );
/* set PCI GART page-table base address
*/
RADEON_WRITE( RADEON_AIC_PT_BASE, dev_priv->bus_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, 0xffffffc0 ); /* ?? */
RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */
} else {
RADEON_WRITE( RADEON_AIC_CNTL, tmp & ~RADEON_PCIGART_TRANSLATE_EN );
}
}
static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
{
drm_radeon_private_t *dev_priv;
u32 tmp;
DRM_DEBUG( "\n" );
dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER );
@ -1153,10 +1179,11 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
(drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle +
init->sarea_priv_offset);
#if __REALLY_HAVE_AGP
if ( !dev_priv->is_pci ) {
DRM_IOREMAP( dev_priv->cp_ring );
DRM_IOREMAP( dev_priv->ring_rptr );
DRM_IOREMAP( dev_priv->buffers );
DRM_IOREMAP( dev_priv->cp_ring, dev );
DRM_IOREMAP( dev_priv->ring_rptr, dev );
DRM_IOREMAP( dev_priv->buffers, dev );
if(!dev_priv->cp_ring->handle ||
!dev_priv->ring_rptr->handle ||
!dev_priv->buffers->handle) {
@ -1165,7 +1192,9 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
} else {
} else
#endif
{
dev_priv->cp_ring->handle =
(void *)dev_priv->cp_ring->offset;
dev_priv->ring_rptr->handle =
@ -1212,8 +1241,13 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
#if __REALLY_HAVE_SG
if ( dev_priv->is_pci ) {
#if __REALLY_HAVE_AGP
if ( !dev_priv->is_pci ) {
/* Turn off PCI GART */
radeon_set_pcigart( dev_priv, 0 );
} else
#endif
{
if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart,
&dev_priv->bus_pci_gart)) {
DRM_ERROR( "failed to init PCI GART!\n" );
@ -1221,36 +1255,10 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
radeon_do_cleanup_cp(dev);
return DRM_ERR(ENOMEM);
}
/* 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, dev_priv->bus_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, 0xffffffc0 ); /* ?? */
RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */
} else {
#endif /* __REALLY_HAVE_SG */
/* Turn off PCI GART
*/
tmp = RADEON_READ( RADEON_AIC_CNTL )
& ~RADEON_PCIGART_TRANSLATE_EN;
RADEON_WRITE( RADEON_AIC_CNTL, tmp );
#if __REALLY_HAVE_SG
/* Turn on PCI GART */
radeon_set_pcigart( dev_priv, 1 );
}
#endif /* __REALLY_HAVE_SG */
radeon_cp_load_microcode( dev_priv );
radeon_cp_init_ring_buffer( dev, dev_priv );
@ -1268,23 +1276,32 @@ int radeon_do_cleanup_cp( drm_device_t *dev )
{
DRM_DEBUG( "\n" );
#if _HAVE_DMA_IRQ
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
* is freed, it's too late.
*/
if ( dev->irq ) DRM(irq_uninstall)(dev);
#endif
if ( dev->dev_private ) {
drm_radeon_private_t *dev_priv = dev->dev_private;
#if __REALLY_HAVE_AGP
if ( !dev_priv->is_pci ) {
if ( dev_priv->cp_ring != NULL )
DRM_IOREMAPFREE( dev_priv->cp_ring );
DRM_IOREMAPFREE( dev_priv->cp_ring, dev );
if ( dev_priv->ring_rptr != NULL )
DRM_IOREMAPFREE( dev_priv->ring_rptr );
DRM_IOREMAPFREE( dev_priv->ring_rptr, dev );
if ( dev_priv->buffers != NULL )
DRM_IOREMAPFREE( dev_priv->buffers );
} else {
#if __REALLY_HAVE_SG
DRM_IOREMAPFREE( dev_priv->buffers, dev );
} else
#endif
{
if (!DRM(ati_pcigart_cleanup)( dev,
dev_priv->phys_pci_gart,
dev_priv->bus_pci_gart ))
DRM_ERROR( "failed to cleanup PCI GART!\n" );
#endif /* __REALLY_HAVE_SG */
}
DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t),
@ -1295,11 +1312,53 @@ int radeon_do_cleanup_cp( drm_device_t *dev )
return 0;
}
/* This code will reinit the Radeon CP hardware after a resume from disc.
* AFAIK, it would be very difficult to pickle the state at suspend time, so
* here we make sure that all Radeon hardware initialisation is re-done without
* affecting running applications.
*
* Charl P. Botha <http://cpbotha.net>
*/
static int radeon_do_resume_cp( drm_device_t *dev )
{
drm_radeon_private_t *dev_priv = dev->dev_private;
if ( !dev_priv ) {
DRM_ERROR( "Called with no initialization\n" );
return DRM_ERR( EINVAL );
}
DRM_DEBUG("Starting radeon_do_resume_cp()\n");
#if __REALLY_HAVE_AGP
if ( !dev_priv->is_pci ) {
/* Turn off PCI GART */
radeon_set_pcigart( dev_priv, 0 );
} else
#endif
{
/* Turn on PCI GART */
radeon_set_pcigart( dev_priv, 1 );
}
radeon_cp_load_microcode( dev_priv );
radeon_cp_init_ring_buffer( dev, dev_priv );
radeon_do_engine_reset( dev );
DRM_DEBUG("radeon_do_resume_cp() complete\n");
return 0;
}
int radeon_cp_init( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_init_t init;
LOCK_TEST_WITH_RETURN( dev, filp );
DRM_COPY_FROM_USER_IOCTL( init, (drm_radeon_init_t *)data, sizeof(init) );
switch ( init.func ) {
@ -1448,6 +1507,16 @@ int radeon_cp_idle( DRM_IOCTL_ARGS )
return radeon_do_cp_idle( dev_priv );
}
/* Added by Charl P. Botha to call radeon_do_resume_cp().
*/
int radeon_cp_resume( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
return radeon_do_resume_cp(dev);
}
int radeon_engine_reset( DRM_IOCTL_ARGS )
{
DRM_DEVICE;

View File

@ -143,7 +143,10 @@
#define R200_EMIT_PP_CUBIC_OFFSETS_4 70
#define R200_EMIT_PP_CUBIC_FACES_5 71
#define R200_EMIT_PP_CUBIC_OFFSETS_5 72
#define RADEON_MAX_STATE_PACKETS 73
#define RADEON_EMIT_PP_TEX_SIZE_0 73
#define RADEON_EMIT_PP_TEX_SIZE_1 74
#define RADEON_EMIT_PP_TEX_SIZE_2 75
#define RADEON_MAX_STATE_PACKETS 76
/* Commands understood by cmd_buffer ioctl. More can be added but
@ -324,12 +327,6 @@ typedef struct {
} drm_radeon_state_t;
typedef struct {
unsigned char next, prev;
unsigned char in_use;
int age;
} drm_radeon_tex_region_t;
typedef struct {
/* The channel for communication of state information to the
* kernel on firing a vertex buffer with either of the
@ -352,8 +349,8 @@ typedef struct {
unsigned int last_dispatch;
unsigned int last_clear;
drm_radeon_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
int tex_age[RADEON_NR_TEX_HEAPS];
drm_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
unsigned int tex_age[RADEON_NR_TEX_HEAPS];
int ctx_owner;
int pfState; /* number of 3d windows (0,1,2ormore) */
int pfCurrentPage; /* which buffer is being displayed? */
@ -393,6 +390,8 @@ typedef struct {
#define DRM_IOCTL_RADEON_INIT_HEAP DRM_IOW( 0x55, drm_radeon_mem_init_heap_t)
#define DRM_IOCTL_RADEON_IRQ_EMIT DRM_IOWR( 0x56, drm_radeon_irq_emit_t)
#define DRM_IOCTL_RADEON_IRQ_WAIT DRM_IOW( 0x57, drm_radeon_irq_wait_t)
/* added by Charl P. Botha - see radeon_cp.c for details */
#define DRM_IOCTL_RADEON_CP_RESUME DRM_IO(0x58)
typedef struct drm_radeon_init {
enum {
@ -532,8 +531,10 @@ typedef struct drm_radeon_indirect {
#define RADEON_PARAM_LAST_FRAME 2
#define RADEON_PARAM_LAST_DISPATCH 3
#define RADEON_PARAM_LAST_CLEAR 4
/* Added with DRM version 1.6. */
#define RADEON_PARAM_IRQ_NR 5
#define RADEON_PARAM_AGP_BASE 6 /* card offset of agp base */
/* Added with DRM version 1.8. */
#define RADEON_PARAM_REGISTER_HANDLE 7 /* for drmMap() */
#define RADEON_PARAM_STATUS_HANDLE 8
#define RADEON_PARAM_SAREA_HANDLE 9

View File

@ -88,6 +88,7 @@ drm_chipinfo_t DRM(devicelist)[] = {
#include "dev/drm/drm_ioctl.h"
#include "dev/drm/drm_lock.h"
#include "dev/drm/drm_memory.h"
#include "dev/drm/drm_pci.h"
#include "dev/drm/drm_vm.h"
#include "dev/drm/drm_sysctl.h"
#if __HAVE_SG

View File

@ -161,6 +161,7 @@ extern int radeon_cp_start( DRM_IOCTL_ARGS );
extern int radeon_cp_stop( DRM_IOCTL_ARGS );
extern int radeon_cp_reset( DRM_IOCTL_ARGS );
extern int radeon_cp_idle( DRM_IOCTL_ARGS );
extern int radeon_cp_resume( DRM_IOCTL_ARGS );
extern int radeon_engine_reset( DRM_IOCTL_ARGS );
extern int radeon_fullscreen( DRM_IOCTL_ARGS );
extern int radeon_cp_buffers( DRM_IOCTL_ARGS );
@ -583,6 +584,7 @@ extern void radeon_do_release(drm_device_t *dev);
#define RADEON_TXFORMAT_ARGB4444 5
#define RADEON_TXFORMAT_ARGB8888 6
#define RADEON_TXFORMAT_RGBA8888 7
#define RADEON_TXFORMAT_Y8 8
#define RADEON_TXFORMAT_VYUY422 10
#define RADEON_TXFORMAT_YVYU422 11
#define RADEON_TXFORMAT_DXT1 12
@ -669,6 +671,10 @@ extern void radeon_do_release(drm_device_t *dev);
#define R200_RE_POINTSIZE 0x2648
#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254
#define RADEON_PP_TEX_SIZE_0 0x1d04 /* NPOT */
#define RADEON_PP_TEX_SIZE_1 0x1d0c
#define RADEON_PP_TEX_SIZE_2 0x1d14
#define SE_VAP_CNTL__TCL_ENA_MASK 0x00000001
#define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK 0x00010000
@ -854,7 +860,7 @@ do { \
#define COMMIT_RING() do { \
/* Flush writes to ring */ \
DRM_READMEMORYBARRIER( dev_priv->mmio ); \
DRM_MEMORYBARRIER(); \
GET_RING_HEAD( dev_priv ); \
RADEON_WRITE( RADEON_CP_RB_WPTR, dev_priv->ring.tail ); \
/* read from PCI bus to ensure correct posting */ \

View File

@ -56,7 +56,7 @@
* tied to dma at all, this is just a hangover from dri prehistory.
*/
void DRM(dma_service)( DRM_IRQ_ARGS )
irqreturn_t DRM(dma_service)( DRM_IRQ_ARGS )
{
drm_device_t *dev = (drm_device_t *) arg;
drm_radeon_private_t *dev_priv =
@ -69,7 +69,7 @@ void DRM(dma_service)( DRM_IRQ_ARGS )
stat = RADEON_READ(RADEON_GEN_INT_STATUS)
& (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT);
if (!stat)
return;
return IRQ_NONE;
/* SW interrupt */
if (stat & RADEON_SW_INT_TEST) {
@ -85,6 +85,7 @@ void DRM(dma_service)( DRM_IRQ_ARGS )
/* Acknowledge interrupts we handle */
RADEON_WRITE(RADEON_GEN_INT_STATUS, stat);
return IRQ_HANDLED;
}
static __inline__ void radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv)
@ -251,8 +252,9 @@ void DRM(driver_irq_postinstall)( drm_device_t *dev ) {
void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *)dev->dev_private;
if ( dev_priv ) {
/* Disable *all* interrupts */
RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
}
if (!dev_priv)
return;
/* Disable *all* interrupts */
RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
}

View File

@ -294,6 +294,9 @@ static struct {
{ R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4" },
{ R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5" },
{ R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5" },
{ RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0" },
{ RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1" },
{ RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_1" },
};
@ -887,15 +890,14 @@ typedef struct {
static void radeon_cp_dispatch_vertex( drm_device_t *dev,
drm_buf_t *buf,
drm_radeon_tcl_prim_t *prim,
drm_clip_rect_t *boxes,
int nbox )
drm_radeon_tcl_prim_t *prim )
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_clip_rect_t box;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
int offset = dev_priv->agp_buffers_offset + buf->offset + prim->start;
int numverts = (int)prim->numverts;
int nbox = sarea_priv->nbox;
int i = 0;
RING_LOCALS;
@ -915,10 +917,8 @@ static void radeon_cp_dispatch_vertex( drm_device_t *dev,
do {
/* Emit the next cliprect */
if ( i < nbox ) {
if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) ))
return;
radeon_emit_clip_rect( dev_priv, &box );
radeon_emit_clip_rect( dev_priv,
&sarea_priv->boxes[i] );
}
/* Emit the vertex buffer rendering commands */
@ -997,18 +997,17 @@ static void radeon_cp_dispatch_indirect( drm_device_t *dev,
static void radeon_cp_dispatch_indices( drm_device_t *dev,
drm_buf_t *elt_buf,
drm_radeon_tcl_prim_t *prim,
drm_clip_rect_t *boxes,
int nbox )
drm_radeon_tcl_prim_t *prim )
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_clip_rect_t box;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
int offset = dev_priv->agp_buffers_offset + prim->offset;
u32 *data;
int dwords;
int i = 0;
int start = prim->start + RADEON_INDEX_PRIM_OFFSET;
int count = (prim->finish - start) / sizeof(u16);
int nbox = sarea_priv->nbox;
DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n",
prim->prim,
@ -1047,12 +1046,9 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev,
(count << RADEON_NUM_VERTICES_SHIFT) );
do {
if ( i < nbox ) {
if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) ))
return;
radeon_emit_clip_rect( dev_priv, &box );
}
if ( i < nbox )
radeon_emit_clip_rect( dev_priv,
&sarea_priv->boxes[i] );
radeon_cp_dispatch_indirect( dev, elt_buf,
prim->start,
@ -1452,9 +1448,7 @@ int radeon_cp_vertex( DRM_IOCTL_ARGS )
prim.numverts = vertex.count;
prim.vc_format = dev_priv->sarea_priv->vc_format;
radeon_cp_dispatch_vertex( dev, buf, &prim,
dev_priv->sarea_priv->boxes,
dev_priv->sarea_priv->nbox );
radeon_cp_dispatch_vertex( dev, buf, &prim );
}
if (vertex.discard) {
@ -1552,9 +1546,7 @@ int radeon_cp_indices( DRM_IOCTL_ARGS )
prim.numverts = RADEON_MAX_VB_VERTS; /* duh */
prim.vc_format = dev_priv->sarea_priv->vc_format;
radeon_cp_dispatch_indices( dev, buf, &prim,
dev_priv->sarea_priv->boxes,
dev_priv->sarea_priv->nbox );
radeon_cp_dispatch_indices( dev, buf, &prim );
if (elts.discard) {
radeon_cp_discard_buffer( dev, buf );
}
@ -1771,16 +1763,12 @@ int radeon_cp_vertex2( DRM_IOCTL_ARGS )
tclprim.offset = prim.numverts * 64;
tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
radeon_cp_dispatch_indices( dev, buf, &tclprim,
sarea_priv->boxes,
sarea_priv->nbox);
radeon_cp_dispatch_indices( dev, buf, &tclprim );
} else {
tclprim.numverts = prim.numverts;
tclprim.offset = 0; /* not used */
radeon_cp_dispatch_vertex( dev, buf, &tclprim,
sarea_priv->boxes,
sarea_priv->nbox);
radeon_cp_dispatch_vertex( dev, buf, &tclprim );
}
if (sarea_priv->nbox == 1)