summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-core/Config.in16
-rw-r--r--linux-core/Makefile.kernel103
-rw-r--r--linux-core/drm_bufs.c368
-rw-r--r--linux-core/drm_context.c26
-rw-r--r--linux-core/drm_drv.c73
-rw-r--r--linux-core/drm_fops.c2
-rw-r--r--linux-core/drm_ioctl.c15
-rw-r--r--linux-core/drm_scatter.c1
-rw-r--r--linux-core/drm_stub.c1
-rw-r--r--linux-core/drm_vm.c30
-rw-r--r--linux-core/i810_dma.c37
-rw-r--r--linux-core/i810_drv.c4
-rw-r--r--linux-core/r128_drv.c6
-rw-r--r--linux/Config.in16
-rw-r--r--linux/Makefile.kernel103
-rw-r--r--linux/drm_bufs.h368
-rw-r--r--linux/drm_context.h26
-rw-r--r--linux/drm_drv.h73
-rw-r--r--linux/drm_fops.h2
-rw-r--r--linux/drm_ioctl.h15
-rw-r--r--linux/drm_lists.h5
-rw-r--r--linux/drm_scatter.h1
-rw-r--r--linux/drm_stub.h1
-rw-r--r--linux/drm_vm.h30
-rw-r--r--linux/i810_dma.c37
-rw-r--r--linux/i810_drv.c4
-rw-r--r--linux/mga_dma.c77
-rw-r--r--linux/mga_drv.h4
-rw-r--r--linux/mga_warp.c9
-rw-r--r--linux/r128_cce.c81
-rw-r--r--linux/r128_drv.c6
-rw-r--r--linux/r128_state.c16
-rw-r--r--linux/radeon_bufs.c298
-rw-r--r--linux/radeon_cp.c86
34 files changed, 1048 insertions, 892 deletions
diff --git a/linux-core/Config.in b/linux-core/Config.in
new file mode 100644
index 00000000..4936c6b3
--- /dev/null
+++ b/linux-core/Config.in
@@ -0,0 +1,16 @@
+#
+# drm device configuration
+#
+# This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+#
+
+bool 'Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)' CONFIG_DRM
+if [ "$CONFIG_DRM" != "n" ]; then
+ tristate ' 3dfx Banshee/Voodoo3+' CONFIG_DRM_TDFX
+ tristate ' 3dlabs GMX 2000' CONFIG_DRM_GAMMA
+ tristate ' ATI Rage 128' CONFIG_DRM_R128
+ dep_tristate ' ATI Radeon' CONFIG_DRM_RADEON $CONFIG_AGP
+ dep_tristate ' Intel I810' CONFIG_DRM_I810 $CONFIG_AGP
+ dep_tristate ' Matrox g200/g400' CONFIG_DRM_MGA $CONFIG_AGP
+fi
diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel
index a39b3cc5..97b507ee 100644
--- a/linux-core/Makefile.kernel
+++ b/linux-core/Makefile.kernel
@@ -1,91 +1,30 @@
#
-# Makefile for the drm device driver. This driver provides support for
-# the Direct Rendering Infrastructure (DRI) in XFree86 4.x.
-#
+# Makefile for the drm device driver. This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
-# drm.o is a fake target -- it is never built
-# The real targets are in the module-list
O_TARGET := drm.o
-
-module-list := gamma.o tdfx.o r128.o radeon.o ffb.o mga.o i810.o
-export-objs := $(patsubst %.o,%_drv.o,$(module-list))
-
-# libs-objs are included in every module so that radical changes to the
-# architecture of the DRM support library can be made at a later time.
-#
-# The downside is that each module is larger, and a system that uses
-# more than one module (i.e., a dual-head system) will use more memory
-# (but a system that uses exactly one module will use the same amount of
-# memory).
-#
-# The upside is that if the DRM support library ever becomes insufficient
-# for new families of cards, a new library can be implemented for those new
-# cards without impacting the drivers for the old cards. This is significant,
-# because testing architectural changes to old cards may be impossible, and
-# may delay the implementation of a better architecture. We've traded slight
-# memory waste (in the dual-head case) for greatly improved long-term
-# maintainability.
-#
-# NOTE: lib-objs will be eliminated in future versions, thereby
-# eliminating the need to compile the .o files into every module, but
-# for now we still need them.
-#
-
-lib-objs := init.o memory.o proc.o auth.o context.o drawable.o bufs.o
-lib-objs += lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.o
-
-ifeq ($(CONFIG_AGP),y)
- lib-objs += agpsupport.o
-else
- ifeq ($(CONFIG_AGP),m)
- lib-objs += agpsupport.o
- endif
-endif
-
-gamma-objs := gamma_drv.o gamma_dma.o
-tdfx-objs := tdfx_drv.o tdfx_context.o
-r128-objs := r128_drv.o r128_cce.o r128_context.o r128_bufs.o \
- r128_state.o
-radeon-objs := radeon_drv.o radeon_cp.o radeon_context.o radeon_bufs.o \
- radeon_state.o
-ffb-objs := ffb_drv.o ffb_context.o
-mga-objs := mga_drv.o mga_dma.o mga_context.o mga_bufs.o \
- mga_state.o
-i810-objs := i810_drv.o i810_dma.o i810_context.o i810_bufs.o
-
-obj-$(CONFIG_DRM_GAMMA) += gamma.o
-obj-$(CONFIG_DRM_TDFX) += tdfx.o
-obj-$(CONFIG_DRM_R128) += r128.o
-obj-$(CONFIG_DRM_RADEON) += radeon.o
-obj-$(CONFIG_DRM_FFB) += ffb.o
-obj-$(CONFIG_DRM_MGA) += mga.o
-obj-$(CONFIG_DRM_I810) += i810.o
-
-
-# When linking into the kernel, link the library just once.
-# If making modules, we include the library into each module
-
-lib-objs-mod := $(patsubst %.o,%-mod.o,$(lib-objs))
-
-ifdef MAKING_MODULES
- lib = drmlib-mod.a
-else
- obj-y += drmlib.a
-endif
+export-objs := gamma_drv.o tdfx_drv.o r128_drv.o mga_drv.o i810_drv.o \
+ ffb_drv.o
+list-multi := gamma.o tdfx.o r128.o mga.o i810.o ffb.o
+
+gamma-objs := gamma_drv.o gamma_dma.o
+tdfx-objs := tdfx_drv.o
+r128-objs := r128_drv.o r128_cce.o r128_state.o
+mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o
+i810-objs := i810_drv.o i810_dma.o
+radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o
+ffb-objs := ffb_drv.o ffb_context.o
+
+obj-$(CONFIG_DRM_GAMMA) += gamma.o
+obj-$(CONFIG_DRM_TDFX) += tdfx.o
+obj-$(CONFIG_DRM_R128) += r128.o
+obj-$(CONFIG_DRM_RADEON)+= radeon.o
+obj-$(CONFIG_DRM_MGA) += mga.o
+obj-$(CONFIG_DRM_I810) += i810.o
+obj-$(CONFIG_DRM_FFB) += ffb.o
include $(TOPDIR)/Rules.make
-$(patsubst %.o,%.c,$(lib-objs-mod)):
- @ln -sf $(subst -mod,,$@) $@
-
-drmlib-mod.a: $(lib-objs-mod)
- rm -f $@
- $(AR) $(EXTRA_ARFLAGS) rcs $@ $(lib-objs-mod)
-
-drmlib.a: $(lib-objs)
- rm -f $@
- $(AR) $(EXTRA_ARFLAGS) rcs $@ $(lib-objs)
-
gamma.o: $(gamma-objs) $(lib)
$(LD) -r -o $@ $(gamma-objs) $(lib)
diff --git a/linux-core/drm_bufs.c b/linux-core/drm_bufs.c
index 02502321..e8c62dda 100644
--- a/linux-core/drm_bufs.c
+++ b/linux-core/drm_bufs.c
@@ -266,6 +266,46 @@ int DRM(rmmap)(struct inode *inode, struct file *filp,
#if __HAVE_DMA
+
+static void DRM(cleanup_buf_error)(drm_buf_entry_t *entry)
+{
+ int i;
+
+ if (entry->seg_count) {
+ for (i = 0; i < entry->seg_count; i++) {
+ DRM(free_pages)(entry->seglist[i],
+ entry->page_order,
+ DRM_MEM_DMA);
+ }
+ DRM(free)(entry->seglist,
+ entry->seg_count *
+ sizeof(*entry->seglist),
+ DRM_MEM_SEGS);
+
+ entry->seg_count = 0;
+ }
+
+ 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);
+ }
+ }
+ DRM(free)(entry->buflist,
+ entry->buf_count *
+ sizeof(*entry->buflist),
+ DRM_MEM_BUFS);
+
+#if __HAVE_DMA_FREELIST
+ DRM(freelist_destroy)(&entry->freelist);
+#endif
+
+ entry->buf_count = 0;
+ }
+}
+
#if __REALLY_HAVE_AGP
int DRM(addbufs_agp)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
@@ -286,6 +326,7 @@ int DRM(addbufs_agp)( struct inode *inode, struct file *filp,
int total;
int byte_count;
int i;
+ drm_buf_t **temp_buflist;
if ( !dma ) return -EINVAL;
@@ -371,6 +412,11 @@ int DRM(addbufs_agp)( struct inode *inode, struct file *filp,
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) {
+ /* Set count correctly so we free the proper amount. */
+ entry->buf_count = count;
+ DRM(cleanup_buf_error)(entry);
+ }
memset( buf->dev_private, 0, buf->dev_priv_size );
#if __HAVE_DMA_HISTOGRAM
@@ -389,11 +435,20 @@ int DRM(addbufs_agp)( struct inode *inode, struct file *filp,
DRM_DEBUG( "byte_count: %d\n", byte_count );
- dma->buflist = DRM(realloc)( dma->buflist,
+ temp_buflist = DRM(realloc)( dma->buflist,
dma->buf_count * sizeof(*dma->buflist),
(dma->buf_count + entry->buf_count)
* sizeof(*dma->buflist),
DRM_MEM_BUFS );
+ if(!temp_buflist) {
+ /* Free the entry because it isn't valid */
+ DRM(cleanup_buf_error)(entry);
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+ dma->buflist = temp_buflist;
+
for ( i = 0 ; i < entry->buf_count ; i++ ) {
dma->buflist[i + dma->buf_count] = &entry->buflist[i];
}
@@ -446,6 +501,8 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp,
int i;
int byte_count;
int page_count;
+ unsigned long *temp_pagelist;
+ drm_buf_t **temp_buflist;
if ( !dma ) return -EINVAL;
@@ -512,11 +569,24 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp,
}
memset( entry->seglist, 0, count * sizeof(*entry->seglist) );
- dma->pagelist = DRM(realloc)( dma->pagelist,
+ 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 );
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+
+ dma->pagelist = temp_pagelist;
DRM_DEBUG( "pagelist: %d entries\n",
dma->page_count + (count << page_order) );
@@ -563,11 +633,20 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp,
byte_count += PAGE_SIZE << page_order;
}
- dma->buflist = DRM(realloc)( dma->buflist,
+ temp_buflist = DRM(realloc)( dma->buflist,
dma->buf_count * sizeof(*dma->buflist),
(dma->buf_count + entry->buf_count)
* sizeof(*dma->buflist),
DRM_MEM_BUFS );
+ if(!temp_buflist) {
+ /* Free the entry because it isn't valid */
+ DRM(cleanup_buf_error)(entry);
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+ dma->buflist = temp_buflist;
+
for ( i = 0 ; i < entry->buf_count ; i++ ) {
dma->buflist[i + dma->buf_count] = &entry->buflist[i];
}
@@ -601,67 +680,68 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp,
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 */
- }
+ 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;
+ drm_buf_t **temp_buflist;
+
+ 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 */
+ }
if (count < 0 || count > 4096) {
up( &dev->struct_sem );
@@ -669,90 +749,108 @@ int DRM(addbufs_sg)( struct inode *inode, struct file *filp,
return -EINVAL;
}
- 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 );
+ 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) );
-#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 );
+ 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 );
+ if(!buf->dev_private) {
+ /* Set count correctly so we free the proper amount. */
+ entry->buf_count = count;
+ DRM(cleanup_buf_error)(entry);
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
- offset += alignment;
- entry->buf_count++;
- byte_count += PAGE_SIZE << page_order;
- }
+ memset( buf->dev_private, 0, buf->dev_priv_size );
- DRM_DEBUG( "byte_count: %d\n", byte_count );
+# 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 );
+
+ temp_buflist = DRM(realloc)( dma->buflist,
+ dma->buf_count * sizeof(*dma->buflist),
+ (dma->buf_count + entry->buf_count)
+ * sizeof(*dma->buflist),
+ DRM_MEM_BUFS );
+ if(!temp_buflist) {
+ /* Free the entry because it isn't valid */
+ DRM(cleanup_buf_error)(entry);
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+ dma->buflist = temp_buflist;
- 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];
- }
+ 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;
+ 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 );
+ 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] );
- }
+ 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 );
+ up( &dev->struct_sem );
- request.count = entry->buf_count;
- request.size = size;
+ request.count = entry->buf_count;
+ request.size = size;
- if ( copy_to_user( (drm_buf_desc_t *)arg, &request, sizeof(request) ) )
- return -EFAULT;
+ if ( copy_to_user( (drm_buf_desc_t *)arg, &request, sizeof(request) ) )
+ return -EFAULT;
- dma->flags = _DRM_DMA_USE_SG;
+ dma->flags = _DRM_DMA_USE_SG;
- atomic_dec( &dev->buf_alloc );
- return 0;
+ atomic_dec( &dev->buf_alloc );
+ return 0;
}
#endif /* __HAVE_SG */
diff --git a/linux-core/drm_context.c b/linux-core/drm_context.c
index 4ac896ef..5e54d81a 100644
--- a/linux-core/drm_context.c
+++ b/linux-core/drm_context.c
@@ -70,13 +70,20 @@ int DRM(ctxbitmap_next)( drm_device_t *dev )
if((bit+1) > dev->max_context) {
dev->max_context = (bit+1);
if(dev->context_sareas) {
- dev->context_sareas = DRM(realloc)(
- dev->context_sareas,
- (dev->max_context - 1) *
- sizeof(*dev->context_sareas),
- dev->max_context *
- sizeof(*dev->context_sareas),
- DRM_MEM_MAPS);
+ drm_map_t **ctx_sareas;
+
+ ctx_sareas = DRM(realloc)(dev->context_sareas,
+ (dev->max_context - 1) *
+ sizeof(*dev->context_sareas),
+ dev->max_context *
+ sizeof(*dev->context_sareas),
+ DRM_MEM_MAPS);
+ if(!ctx_sareas) {
+ clear_bit(bit, dev->ctx_bitmap);
+ up(&dev->struct_sem);
+ return -1;
+ }
+ dev->context_sareas = ctx_sareas;
dev->context_sareas[bit] = NULL;
} else {
/* max_context == 1 at this point */
@@ -84,6 +91,11 @@ int DRM(ctxbitmap_next)( drm_device_t *dev )
dev->max_context *
sizeof(*dev->context_sareas),
DRM_MEM_MAPS);
+ if(!dev->context_sareas) {
+ clear_bit(bit, dev->ctx_bitmap);
+ up(&dev->struct_sem);
+ return -1;
+ }
dev->context_sareas[bit] = NULL;
}
}
diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c
index dd46f227..a28b0b5b 100644
--- a/linux-core/drm_drv.c
+++ b/linux-core/drm_drv.c
@@ -84,6 +84,9 @@
#ifndef __HAVE_SG
#define __HAVE_SG 0
#endif
+#ifndef __HAVE_KERNEL_CTX_SWITCH
+#define __HAVE_KERNEL_CTX_SWITCH 0
+#endif
#ifndef DRIVER_PREINIT
#define DRIVER_PREINIT()
@@ -97,9 +100,47 @@
#ifndef DRIVER_PRETAKEDOWN
#define DRIVER_PRETAKEDOWN()
#endif
+#ifndef DRIVER_POSTCLEANUP
+#define DRIVER_POSTCLEANUP()
+#endif
+#ifndef DRIVER_PRESETUP
+#define DRIVER_PRESETUP()
+#endif
+#ifndef DRIVER_POSTSETUP
+#define DRIVER_POSTSETUP()
+#endif
#ifndef DRIVER_IOCTLS
#define DRIVER_IOCTLS
#endif
+#ifndef DRIVER_FOPS
+#if LINUX_VERSION_CODE >= 0x020400
+#define DRIVER_FOPS \
+static struct file_operations DRM(fops) = { \
+ owner: THIS_MODULE, \
+ open: DRM(open), \
+ flush: DRM(flush), \
+ release: DRM(release), \
+ ioctl: DRM(ioctl), \
+ mmap: DRM(mmap), \
+ read: DRM(read), \
+ fasync: DRM(fasync), \
+ poll: DRM(poll), \
+}
+#else
+#define DRIVER_FOPS \
+static struct file_operations DRM(fops) = { \
+ open: DRM(open), \
+ flush: DRM(flush), \
+ release: DRM(release), \
+ ioctl: DRM(ioctl), \
+ mmap: DRM(mmap), \
+ read: DRM(read), \
+ fasync: DRM(fasync), \
+ poll: DRM(poll), \
+}
+#endif
+#endif
+
/*
* The default number of instances (minor numbers) to initialize.
@@ -112,21 +153,7 @@ static drm_device_t *DRM(device);
static int *DRM(minor);
static int DRM(numdevs) = 0;
-static struct file_operations DRM(fops) = {
-#if LINUX_VERSION_CODE >= 0x020400
- /* This started being used during 2.4.0-test */
- owner: THIS_MODULE,
-#endif
- open: DRM(open),
- flush: DRM(flush),
- release: DRM(release),
- ioctl: DRM(ioctl),
- mmap: DRM(mmap),
- read: DRM(read),
- fasync: DRM(fasync),
- poll: DRM(poll),
-};
-
+DRIVER_FOPS;
static drm_ioctl_desc_t DRM(ioctls)[] = {
[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { DRM(version), 0, 0 },
@@ -212,6 +239,7 @@ static int DRM(setup)( drm_device_t *dev )
{
int i;
+ DRIVER_PRESETUP();
atomic_set( &dev->ioctl_count, 0 );
atomic_set( &dev->vma_count, 0 );
dev->buf_use = 0;
@@ -311,6 +339,7 @@ static int DRM(setup)( drm_device_t *dev )
* drm_select_queue fails between the time the interrupt is
* initialized and the time the queues are initialized.
*/
+ DRIVER_POSTSETUP();
return 0;
}
@@ -320,7 +349,7 @@ static int DRM(takedown)( drm_device_t *dev )
drm_magic_entry_t *pt, *next;
drm_map_t *map;
drm_map_list_t *r_list;
- struct list_head *list;
+ struct list_head *list, *list_next;
drm_vma_entry_t *vma, *vma_next;
int i;
@@ -388,7 +417,10 @@ static int DRM(takedown)( drm_device_t *dev )
}
if( dev->maplist ) {
- list_for_each(list, &dev->maplist->head) {
+ for(list = dev->maplist->head.next;
+ list != &dev->maplist->head;
+ list = list_next) {
+ list_next = list->next;
r_list = (drm_map_list_t *)list;
map = r_list->map;
DRM(free)(r_list, sizeof(*r_list), DRM_MEM_MAPS);
@@ -635,6 +667,7 @@ static void __exit drm_cleanup( void )
}
#endif
}
+ DRIVER_POSTCLEANUP();
kfree(DRM(minor));
kfree(DRM(device));
DRM(numdevs) = 0;
@@ -979,6 +1012,12 @@ int DRM(lock)( struct inode *inode, struct file *filp,
DRIVER_DMA_QUIESCENT();
}
#endif
+#if __HAVE_KERNEL_CTX_SWITCH
+ if ( dev->last_context != lock.context ) {
+ DRM(context_switch)(dev, dev->last_context,
+ lock.context);
+ }
+#endif
}
DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
diff --git a/linux-core/drm_fops.c b/linux-core/drm_fops.c
index 75752b3a..3656c5e9 100644
--- a/linux-core/drm_fops.c
+++ b/linux-core/drm_fops.c
@@ -47,6 +47,8 @@ int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
priv = DRM(alloc)(sizeof(*priv), DRM_MEM_FILES);
+ if(!priv) return -ENOMEM;
+
memset(priv, 0, sizeof(*priv));
filp->private_data = priv;
priv->uid = current->euid;
diff --git a/linux-core/drm_ioctl.c b/linux-core/drm_ioctl.c
index c2761808..4712cbd3 100644
--- a/linux-core/drm_ioctl.c
+++ b/linux-core/drm_ioctl.c
@@ -76,23 +76,26 @@ int DRM(setunique)(struct inode *inode, struct file *filp,
drm_device_t *dev = priv->dev;
drm_unique_t u;
- if (dev->unique_len || dev->unique)
- return -EBUSY;
+ if (dev->unique_len || dev->unique) return -EBUSY;
- if (copy_from_user(&u, (drm_unique_t *)arg, sizeof(u)))
- return -EFAULT;
+ if (copy_from_user(&u, (drm_unique_t *)arg, sizeof(u))) return -EFAULT;
- if (!u.unique_len || u.unique_len > 1024)
- return -EINVAL;
+ if (!u.unique_len || u.unique_len > 1024) return -EINVAL;
dev->unique_len = u.unique_len;
dev->unique = DRM(alloc)(u.unique_len + 1, DRM_MEM_DRIVER);
+ if(!dev->unique) return -ENOMEM;
if (copy_from_user(dev->unique, u.unique, dev->unique_len))
return -EFAULT;
+
dev->unique[dev->unique_len] = '\0';
dev->devname = DRM(alloc)(strlen(dev->name) + strlen(dev->unique) + 2,
DRM_MEM_DRIVER);
+ if(!dev->devname) {
+ DRM(free)(dev->devname, sizeof(*dev->devname), DRM_MEM_DRIVER);
+ return -ENOMEM;
+ }
sprintf(dev->devname, "%s@%s", dev->name, dev->unique);
#ifdef __alpha__
diff --git a/linux-core/drm_scatter.c b/linux-core/drm_scatter.c
index a0371074..c1c9f7e8 100644
--- a/linux-core/drm_scatter.c
+++ b/linux-core/drm_scatter.c
@@ -93,6 +93,7 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS );
return -ENOMEM;
}
+ memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
entry->virtual = vmalloc_32( pages << PAGE_SHIFT );
if ( !entry->virtual ) {
diff --git a/linux-core/drm_stub.c b/linux-core/drm_stub.c
index 6811d6ba..fe8a1bc9 100644
--- a/linux-core/drm_stub.c
+++ b/linux-core/drm_stub.c
@@ -84,6 +84,7 @@ static int DRM(stub_getminor)(const char *name, struct file_operations *fops,
if (!DRM(stub_list)) {
DRM(stub_list) = DRM(alloc)(sizeof(*DRM(stub_list))
* DRM_STUB_MAXCARDS, DRM_MEM_STUB);
+ if(!DRM(stub_list)) return -1;
for (i = 0; i < DRM_STUB_MAXCARDS; i++) {
DRM(stub_list)[i].name = NULL;
DRM(stub_list)[i].fops = NULL;
diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c
index 4db521de..d8e77f79 100644
--- a/linux-core/drm_vm.c
+++ b/linux-core/drm_vm.c
@@ -126,7 +126,7 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
{
drm_file_t *priv = vma->vm_file->private_data;
drm_device_t *dev = priv->dev;
- drm_vma_entry_t *pt, *prev;
+ drm_vma_entry_t *pt, *prev, *next;
drm_map_t *map;
drm_map_list_t *r_list;
struct list_head *list;
@@ -146,7 +146,8 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
#endif
down(&dev->struct_sem);
- for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
+ for (pt = dev->vmalist, prev = NULL; pt; pt = next) {
+ next = pt->next;
#if LINUX_VERSION_CODE >= 0x020300
if (pt->vma->vm_private_data == map) found_maps++;
#else
@@ -159,6 +160,8 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
dev->vmalist = pt->next;
}
DRM(free)(pt, sizeof(*pt), DRM_MEM_VMAS);
+ } else {
+ prev = pt;
}
}
/* We were the only map that was found */
@@ -365,6 +368,19 @@ int DRM(mmap_dma)(struct file *filp, struct vm_area_struct *vma)
return 0;
}
+#ifndef DRIVER_GET_MAP_OFS
+#define DRIVER_GET_MAP_OFS() (map->offset)
+#endif
+
+#ifndef DRIVER_GET_REG_OFS
+#ifdef __alpha__
+#define DRIVER_GET_REG_OFS() (dev->hose->dense_mem_base - \
+ dev->hose->mem_space->start)
+#else
+#define DRIVER_GET_REG_OFS() 0
+#endif
+#endif
+
int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
{
drm_file_t *priv = filp->private_data;
@@ -389,10 +405,13 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
for performance, even if the list was a
bit longer. */
list_for_each(list, &dev->maplist->head) {
+ unsigned long off;
+
r_list = (drm_map_list_t *)list;
map = r_list->map;
if (!map) continue;
- if (map->offset == VM_OFFSET(vma)) break;
+ off = DRIVER_GET_MAP_OFS();
+ if (off == VM_OFFSET(vma)) break;
}
if (!map || ((map->flags&_DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
@@ -433,10 +452,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
#endif
vma->vm_flags |= VM_IO; /* not in core dump */
}
-#ifdef __alpha__
- offset = dev->hose->dense_mem_base -
- dev->hose->mem_space->start;
-#endif
+ offset = DRIVER_GET_REG_OFS();
if (remap_page_range(vma->vm_start,
VM_OFFSET(vma) + offset,
vma->vm_end - vma->vm_start,
diff --git a/linux-core/i810_dma.c b/linux-core/i810_dma.c
index 75be5d0c..d6933d57 100644
--- a/linux-core/i810_dma.c
+++ b/linux-core/i810_dma.c
@@ -379,10 +379,9 @@ static void i810_kernel_lost_context(drm_device_t *dev)
if (ring->space < 0) ring->space += ring->Size;
}
-static int i810_freelist_init(drm_device_t *dev)
+static int i810_freelist_init(drm_device_t *dev, drm_i810_private_t *dev_priv)
{
drm_device_dma_t *dma = dev->dma;
- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
int my_idx = 24;
u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
int i;
@@ -414,7 +413,6 @@ static int i810_dma_initialize(drm_device_t *dev,
{
struct list_head *list;
- dev->dev_private = (void *) dev_priv;
memset(dev_priv, 0, sizeof(drm_i810_private_t));
list_for_each(list, &dev->maplist->head) {
@@ -426,9 +424,26 @@ static int i810_dma_initialize(drm_device_t *dev,
break;
}
}
-
+ if(!dev_priv->sarea_map) {
+ dev->dev_private = (void *)dev_priv;
+ i810_dma_cleanup(dev);
+ DRM_ERROR("can not find sarea!\n");
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->mmio_map, init->mmio_offset );
+ if(!dev_priv->mmio_map) {
+ dev->dev_private = (void *)dev_priv;
+ i810_dma_cleanup(dev);
+ DRM_ERROR("can not find mmio map!\n");
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->buffer_map, init->buffers_offset );
+ if(!dev_priv->buffer_map) {
+ dev->dev_private = (void *)dev_priv;
+ i810_dma_cleanup(dev);
+ DRM_ERROR("can not find dma buffer map!\n");
+ return -EINVAL;
+ }
dev_priv->sarea_priv = (drm_i810_sarea_t *)
((u8 *)dev_priv->sarea_map->handle +
@@ -445,15 +460,16 @@ static int i810_dma_initialize(drm_device_t *dev,
init->ring_start,
init->ring_size);
- dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
-
if (dev_priv->ring.virtual_start == NULL) {
+ dev->dev_private = (void *) dev_priv;
i810_dma_cleanup(dev);
DRM_ERROR("can not ioremap virtual address for"
" ring buffer\n");
return -ENOMEM;
}
+ dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+
dev_priv->w = init->w;
dev_priv->h = init->h;
dev_priv->pitch = init->pitch;
@@ -464,27 +480,30 @@ static int i810_dma_initialize(drm_device_t *dev,
dev_priv->back_di1 = init->back_offset | init->pitch_bits;
dev_priv->zi1 = init->depth_offset | init->pitch_bits;
-
/* Program Hardware Status Page */
dev_priv->hw_status_page = i810_alloc_page(dev);
- memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE);
if(dev_priv->hw_status_page == 0UL) {
+ dev->dev_private = (void *)dev_priv;
i810_dma_cleanup(dev);
DRM_ERROR("Can not allocate hardware status page\n");
return -ENOMEM;
}
+ memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE);
DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page);
I810_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page));
DRM_DEBUG("Enabled hardware status page\n");
/* Now we need to init our freelist */
- if(i810_freelist_init(dev) != 0) {
+ if(i810_freelist_init(dev, dev_priv) != 0) {
+ dev->dev_private = (void *)dev_priv;
i810_dma_cleanup(dev);
DRM_ERROR("Not enough space in the status page for"
" the freelist\n");
return -ENOMEM;
}
+ dev->dev_private = (void *)dev_priv;
+
return 0;
}
diff --git a/linux-core/i810_drv.c b/linux-core/i810_drv.c
index d21a19b7..a228cb46 100644
--- a/linux-core/i810_drv.c
+++ b/linux-core/i810_drv.c
@@ -41,8 +41,8 @@
#define DRIVER_DESC "Intel i810"
#define DRIVER_DATE "20010616"
-#define DRIVER_MAJOR 2
-#define DRIVER_MINOR 0
+#define DRIVER_MAJOR 1
+#define DRIVER_MINOR 1
#define DRIVER_PATCHLEVEL 0
#define DRIVER_IOCTLS \
diff --git a/linux-core/r128_drv.c b/linux-core/r128_drv.c
index 4f0bb92b..d4eda6c8 100644
--- a/linux-core/r128_drv.c
+++ b/linux-core/r128_drv.c
@@ -41,9 +41,9 @@
#define DRIVER_DESC "ATI Rage 128"
#define DRIVER_DATE "20010405"
-#define DRIVER_MAJOR 3
-#define DRIVER_MINOR 0
-#define DRIVER_PATCHLEVEL 0
+#define DRIVER_MAJOR 2
+#define DRIVER_MINOR 1
+#define DRIVER_PATCHLEVEL 6
#define DRIVER_IOCTLS \
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { r128_cce_buffers, 1, 0 }, \
diff --git a/linux/Config.in b/linux/Config.in
new file mode 100644
index 00000000..4936c6b3
--- /dev/null
+++ b/linux/Config.in
@@ -0,0 +1,16 @@
+#
+# drm device configuration
+#
+# This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+#
+
+bool 'Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)' CONFIG_DRM
+if [ "$CONFIG_DRM" != "n" ]; then
+ tristate ' 3dfx Banshee/Voodoo3+' CONFIG_DRM_TDFX
+ tristate ' 3dlabs GMX 2000' CONFIG_DRM_GAMMA
+ tristate ' ATI Rage 128' CONFIG_DRM_R128
+ dep_tristate ' ATI Radeon' CONFIG_DRM_RADEON $CONFIG_AGP
+ dep_tristate ' Intel I810' CONFIG_DRM_I810 $CONFIG_AGP
+ dep_tristate ' Matrox g200/g400' CONFIG_DRM_MGA $CONFIG_AGP
+fi
diff --git a/linux/Makefile.kernel b/linux/Makefile.kernel
index a39b3cc5..97b507ee 100644
--- a/linux/Makefile.kernel
+++ b/linux/Makefile.kernel
@@ -1,91 +1,30 @@
#
-# Makefile for the drm device driver. This driver provides support for
-# the Direct Rendering Infrastructure (DRI) in XFree86 4.x.
-#
+# Makefile for the drm device driver. This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
-# drm.o is a fake target -- it is never built
-# The real targets are in the module-list
O_TARGET := drm.o
-
-module-list := gamma.o tdfx.o r128.o radeon.o ffb.o mga.o i810.o
-export-objs := $(patsubst %.o,%_drv.o,$(module-list))
-
-# libs-objs are included in every module so that radical changes to the
-# architecture of the DRM support library can be made at a later time.
-#
-# The downside is that each module is larger, and a system that uses
-# more than one module (i.e., a dual-head system) will use more memory
-# (but a system that uses exactly one module will use the same amount of
-# memory).
-#
-# The upside is that if the DRM support library ever becomes insufficient
-# for new families of cards, a new library can be implemented for those new
-# cards without impacting the drivers for the old cards. This is significant,
-# because testing architectural changes to old cards may be impossible, and
-# may delay the implementation of a better architecture. We've traded slight
-# memory waste (in the dual-head case) for greatly improved long-term
-# maintainability.
-#
-# NOTE: lib-objs will be eliminated in future versions, thereby
-# eliminating the need to compile the .o files into every module, but
-# for now we still need them.
-#
-
-lib-objs := init.o memory.o proc.o auth.o context.o drawable.o bufs.o
-lib-objs += lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.o
-
-ifeq ($(CONFIG_AGP),y)
- lib-objs += agpsupport.o
-else
- ifeq ($(CONFIG_AGP),m)
- lib-objs += agpsupport.o
- endif
-endif
-
-gamma-objs := gamma_drv.o gamma_dma.o
-tdfx-objs := tdfx_drv.o tdfx_context.o
-r128-objs := r128_drv.o r128_cce.o r128_context.o r128_bufs.o \
- r128_state.o
-radeon-objs := radeon_drv.o radeon_cp.o radeon_context.o radeon_bufs.o \
- radeon_state.o
-ffb-objs := ffb_drv.o ffb_context.o
-mga-objs := mga_drv.o mga_dma.o mga_context.o mga_bufs.o \
- mga_state.o
-i810-objs := i810_drv.o i810_dma.o i810_context.o i810_bufs.o
-
-obj-$(CONFIG_DRM_GAMMA) += gamma.o
-obj-$(CONFIG_DRM_TDFX) += tdfx.o
-obj-$(CONFIG_DRM_R128) += r128.o
-obj-$(CONFIG_DRM_RADEON) += radeon.o
-obj-$(CONFIG_DRM_FFB) += ffb.o
-obj-$(CONFIG_DRM_MGA) += mga.o
-obj-$(CONFIG_DRM_I810) += i810.o
-
-
-# When linking into the kernel, link the library just once.
-# If making modules, we include the library into each module
-
-lib-objs-mod := $(patsubst %.o,%-mod.o,$(lib-objs))
-
-ifdef MAKING_MODULES
- lib = drmlib-mod.a
-else
- obj-y += drmlib.a
-endif
+export-objs := gamma_drv.o tdfx_drv.o r128_drv.o mga_drv.o i810_drv.o \
+ ffb_drv.o
+list-multi := gamma.o tdfx.o r128.o mga.o i810.o ffb.o
+
+gamma-objs := gamma_drv.o gamma_dma.o
+tdfx-objs := tdfx_drv.o
+r128-objs := r128_drv.o r128_cce.o r128_state.o
+mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o
+i810-objs := i810_drv.o i810_dma.o
+radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o
+ffb-objs := ffb_drv.o ffb_context.o
+
+obj-$(CONFIG_DRM_GAMMA) += gamma.o
+obj-$(CONFIG_DRM_TDFX) += tdfx.o
+obj-$(CONFIG_DRM_R128) += r128.o
+obj-$(CONFIG_DRM_RADEON)+= radeon.o
+obj-$(CONFIG_DRM_MGA) += mga.o
+obj-$(CONFIG_DRM_I810) += i810.o
+obj-$(CONFIG_DRM_FFB) += ffb.o
include $(TOPDIR)/Rules.make
-$(patsubst %.o,%.c,$(lib-objs-mod)):
- @ln -sf $(subst -mod,,$@) $@
-
-drmlib-mod.a: $(lib-objs-mod)
- rm -f $@
- $(AR) $(EXTRA_ARFLAGS) rcs $@ $(lib-objs-mod)
-
-drmlib.a: $(lib-objs)
- rm -f $@
- $(AR) $(EXTRA_ARFLAGS) rcs $@ $(lib-objs)
-
gamma.o: $(gamma-objs) $(lib)
$(LD) -r -o $@ $(gamma-objs) $(lib)
diff --git a/linux/drm_bufs.h b/linux/drm_bufs.h
index 02502321..e8c62dda 100644
--- a/linux/drm_bufs.h
+++ b/linux/drm_bufs.h
@@ -266,6 +266,46 @@ int DRM(rmmap)(struct inode *inode, struct file *filp,
#if __HAVE_DMA
+
+static void DRM(cleanup_buf_error)(drm_buf_entry_t *entry)
+{
+ int i;
+
+ if (entry->seg_count) {
+ for (i = 0; i < entry->seg_count; i++) {
+ DRM(free_pages)(entry->seglist[i],
+ entry->page_order,
+ DRM_MEM_DMA);
+ }
+ DRM(free)(entry->seglist,
+ entry->seg_count *
+ sizeof(*entry->seglist),
+ DRM_MEM_SEGS);
+
+ entry->seg_count = 0;
+ }
+
+ 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);
+ }
+ }
+ DRM(free)(entry->buflist,
+ entry->buf_count *
+ sizeof(*entry->buflist),
+ DRM_MEM_BUFS);
+
+#if __HAVE_DMA_FREELIST
+ DRM(freelist_destroy)(&entry->freelist);
+#endif
+
+ entry->buf_count = 0;
+ }
+}
+
#if __REALLY_HAVE_AGP
int DRM(addbufs_agp)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
@@ -286,6 +326,7 @@ int DRM(addbufs_agp)( struct inode *inode, struct file *filp,
int total;
int byte_count;
int i;
+ drm_buf_t **temp_buflist;
if ( !dma ) return -EINVAL;
@@ -371,6 +412,11 @@ int DRM(addbufs_agp)( struct inode *inode, struct file *filp,
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) {
+ /* Set count correctly so we free the proper amount. */
+ entry->buf_count = count;
+ DRM(cleanup_buf_error)(entry);
+ }
memset( buf->dev_private, 0, buf->dev_priv_size );
#if __HAVE_DMA_HISTOGRAM
@@ -389,11 +435,20 @@ int DRM(addbufs_agp)( struct inode *inode, struct file *filp,
DRM_DEBUG( "byte_count: %d\n", byte_count );
- dma->buflist = DRM(realloc)( dma->buflist,
+ temp_buflist = DRM(realloc)( dma->buflist,
dma->buf_count * sizeof(*dma->buflist),
(dma->buf_count + entry->buf_count)
* sizeof(*dma->buflist),
DRM_MEM_BUFS );
+ if(!temp_buflist) {
+ /* Free the entry because it isn't valid */
+ DRM(cleanup_buf_error)(entry);
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+ dma->buflist = temp_buflist;
+
for ( i = 0 ; i < entry->buf_count ; i++ ) {
dma->buflist[i + dma->buf_count] = &entry->buflist[i];
}
@@ -446,6 +501,8 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp,
int i;
int byte_count;
int page_count;
+ unsigned long *temp_pagelist;
+ drm_buf_t **temp_buflist;
if ( !dma ) return -EINVAL;
@@ -512,11 +569,24 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp,
}
memset( entry->seglist, 0, count * sizeof(*entry->seglist) );
- dma->pagelist = DRM(realloc)( dma->pagelist,
+ 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 );
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+
+ dma->pagelist = temp_pagelist;
DRM_DEBUG( "pagelist: %d entries\n",
dma->page_count + (count << page_order) );
@@ -563,11 +633,20 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp,
byte_count += PAGE_SIZE << page_order;
}
- dma->buflist = DRM(realloc)( dma->buflist,
+ temp_buflist = DRM(realloc)( dma->buflist,
dma->buf_count * sizeof(*dma->buflist),
(dma->buf_count + entry->buf_count)
* sizeof(*dma->buflist),
DRM_MEM_BUFS );
+ if(!temp_buflist) {
+ /* Free the entry because it isn't valid */
+ DRM(cleanup_buf_error)(entry);
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+ dma->buflist = temp_buflist;
+
for ( i = 0 ; i < entry->buf_count ; i++ ) {
dma->buflist[i + dma->buf_count] = &entry->buflist[i];
}
@@ -601,67 +680,68 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp,
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 */
- }
+ 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;
+ drm_buf_t **temp_buflist;
+
+ 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 */
+ }
if (count < 0 || count > 4096) {
up( &dev->struct_sem );
@@ -669,90 +749,108 @@ int DRM(addbufs_sg)( struct inode *inode, struct file *filp,
return -EINVAL;
}
- 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 );
+ 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) );
-#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 );
+ 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 );
+ if(!buf->dev_private) {
+ /* Set count correctly so we free the proper amount. */
+ entry->buf_count = count;
+ DRM(cleanup_buf_error)(entry);
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
- offset += alignment;
- entry->buf_count++;
- byte_count += PAGE_SIZE << page_order;
- }
+ memset( buf->dev_private, 0, buf->dev_priv_size );
- DRM_DEBUG( "byte_count: %d\n", byte_count );
+# 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 );
+
+ temp_buflist = DRM(realloc)( dma->buflist,
+ dma->buf_count * sizeof(*dma->buflist),
+ (dma->buf_count + entry->buf_count)
+ * sizeof(*dma->buflist),
+ DRM_MEM_BUFS );
+ if(!temp_buflist) {
+ /* Free the entry because it isn't valid */
+ DRM(cleanup_buf_error)(entry);
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+ dma->buflist = temp_buflist;
- 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];
- }
+ 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;
+ 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 );
+ 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] );
- }
+ 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 );
+ up( &dev->struct_sem );
- request.count = entry->buf_count;
- request.size = size;
+ request.count = entry->buf_count;
+ request.size = size;
- if ( copy_to_user( (drm_buf_desc_t *)arg, &request, sizeof(request) ) )
- return -EFAULT;
+ if ( copy_to_user( (drm_buf_desc_t *)arg, &request, sizeof(request) ) )
+ return -EFAULT;
- dma->flags = _DRM_DMA_USE_SG;
+ dma->flags = _DRM_DMA_USE_SG;
- atomic_dec( &dev->buf_alloc );
- return 0;
+ atomic_dec( &dev->buf_alloc );
+ return 0;
}
#endif /* __HAVE_SG */
diff --git a/linux/drm_context.h b/linux/drm_context.h
index 4ac896ef..5e54d81a 100644
--- a/linux/drm_context.h
+++ b/linux/drm_context.h
@@ -70,13 +70,20 @@ int DRM(ctxbitmap_next)( drm_device_t *dev )
if((bit+1) > dev->max_context) {
dev->max_context = (bit+1);
if(dev->context_sareas) {
- dev->context_sareas = DRM(realloc)(
- dev->context_sareas,
- (dev->max_context - 1) *
- sizeof(*dev->context_sareas),
- dev->max_context *
- sizeof(*dev->context_sareas),
- DRM_MEM_MAPS);
+ drm_map_t **ctx_sareas;
+
+ ctx_sareas = DRM(realloc)(dev->context_sareas,
+ (dev->max_context - 1) *
+ sizeof(*dev->context_sareas),
+ dev->max_context *
+ sizeof(*dev->context_sareas),
+ DRM_MEM_MAPS);
+ if(!ctx_sareas) {
+ clear_bit(bit, dev->ctx_bitmap);
+ up(&dev->struct_sem);
+ return -1;
+ }
+ dev->context_sareas = ctx_sareas;
dev->context_sareas[bit] = NULL;
} else {
/* max_context == 1 at this point */
@@ -84,6 +91,11 @@ int DRM(ctxbitmap_next)( drm_device_t *dev )
dev->max_context *
sizeof(*dev->context_sareas),
DRM_MEM_MAPS);
+ if(!dev->context_sareas) {
+ clear_bit(bit, dev->ctx_bitmap);
+ up(&dev->struct_sem);
+ return -1;
+ }
dev->context_sareas[bit] = NULL;
}
}
diff --git a/linux/drm_drv.h b/linux/drm_drv.h
index dd46f227..a28b0b5b 100644
--- a/linux/drm_drv.h
+++ b/linux/drm_drv.h
@@ -84,6 +84,9 @@
#ifndef __HAVE_SG
#define __HAVE_SG 0
#endif
+#ifndef __HAVE_KERNEL_CTX_SWITCH
+#define __HAVE_KERNEL_CTX_SWITCH 0
+#endif
#ifndef DRIVER_PREINIT
#define DRIVER_PREINIT()
@@ -97,9 +100,47 @@
#ifndef DRIVER_PRETAKEDOWN
#define DRIVER_PRETAKEDOWN()
#endif
+#ifndef DRIVER_POSTCLEANUP
+#define DRIVER_POSTCLEANUP()
+#endif
+#ifndef DRIVER_PRESETUP
+#define DRIVER_PRESETUP()
+#endif
+#ifndef DRIVER_POSTSETUP
+#define DRIVER_POSTSETUP()
+#endif
#ifndef DRIVER_IOCTLS
#define DRIVER_IOCTLS
#endif
+#ifndef DRIVER_FOPS
+#if LINUX_VERSION_CODE >= 0x020400
+#define DRIVER_FOPS \
+static struct file_operations DRM(fops) = { \
+ owner: THIS_MODULE, \
+ open: DRM(open), \
+ flush: DRM(flush), \
+ release: DRM(release), \
+ ioctl: DRM(ioctl), \
+ mmap: DRM(mmap), \
+ read: DRM(read), \
+ fasync: DRM(fasync), \
+ poll: DRM(poll), \
+}
+#else
+#define DRIVER_FOPS \
+static struct file_operations DRM(fops) = { \
+ open: DRM(open), \
+ flush: DRM(flush), \
+ release: DRM(release), \
+ ioctl: DRM(ioctl), \
+ mmap: DRM(mmap), \
+ read: DRM(read), \
+ fasync: DRM(fasync), \
+ poll: DRM(poll), \
+}
+#endif
+#endif
+
/*
* The default number of instances (minor numbers) to initialize.
@@ -112,21 +153,7 @@ static drm_device_t *DRM(device);
static int *DRM(minor);
static int DRM(numdevs) = 0;
-static struct file_operations DRM(fops) = {
-#if LINUX_VERSION_CODE >= 0x020400
- /* This started being used during 2.4.0-test */
- owner: THIS_MODULE,
-#endif
- open: DRM(open),
- flush: DRM(flush),
- release: DRM(release),
- ioctl: DRM(ioctl),
- mmap: DRM(mmap),
- read: DRM(read),
- fasync: DRM(fasync),
- poll: DRM(poll),
-};
-
+DRIVER_FOPS;
static drm_ioctl_desc_t DRM(ioctls)[] = {
[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { DRM(version), 0, 0 },
@@ -212,6 +239,7 @@ static int DRM(setup)( drm_device_t *dev )
{
int i;
+ DRIVER_PRESETUP();
atomic_set( &dev->ioctl_count, 0 );
atomic_set( &dev->vma_count, 0 );
dev->buf_use = 0;
@@ -311,6 +339,7 @@ static int DRM(setup)( drm_device_t *dev )
* drm_select_queue fails between the time the interrupt is
* initialized and the time the queues are initialized.
*/
+ DRIVER_POSTSETUP();
return 0;
}
@@ -320,7 +349,7 @@ static int DRM(takedown)( drm_device_t *dev )
drm_magic_entry_t *pt, *next;
drm_map_t *map;
drm_map_list_t *r_list;
- struct list_head *list;
+ struct list_head *list, *list_next;
drm_vma_entry_t *vma, *vma_next;
int i;
@@ -388,7 +417,10 @@ static int DRM(takedown)( drm_device_t *dev )
}
if( dev->maplist ) {
- list_for_each(list, &dev->maplist->head) {
+ for(list = dev->maplist->head.next;
+ list != &dev->maplist->head;
+ list = list_next) {
+ list_next = list->next;
r_list = (drm_map_list_t *)list;
map = r_list->map;
DRM(free)(r_list, sizeof(*r_list), DRM_MEM_MAPS);
@@ -635,6 +667,7 @@ static void __exit drm_cleanup( void )
}
#endif
}
+ DRIVER_POSTCLEANUP();
kfree(DRM(minor));
kfree(DRM(device));
DRM(numdevs) = 0;
@@ -979,6 +1012,12 @@ int DRM(lock)( struct inode *inode, struct file *filp,
DRIVER_DMA_QUIESCENT();
}
#endif
+#if __HAVE_KERNEL_CTX_SWITCH
+ if ( dev->last_context != lock.context ) {
+ DRM(context_switch)(dev, dev->last_context,
+ lock.context);
+ }
+#endif
}
DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
diff --git a/linux/drm_fops.h b/linux/drm_fops.h
index 75752b3a..3656c5e9 100644
--- a/linux/drm_fops.h
+++ b/linux/drm_fops.h
@@ -47,6 +47,8 @@ int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
priv = DRM(alloc)(sizeof(*priv), DRM_MEM_FILES);
+ if(!priv) return -ENOMEM;
+
memset(priv, 0, sizeof(*priv));
filp->private_data = priv;
priv->uid = current->euid;
diff --git a/linux/drm_ioctl.h b/linux/drm_ioctl.h
index c2761808..4712cbd3 100644
--- a/linux/drm_ioctl.h
+++ b/linux/drm_ioctl.h
@@ -76,23 +76,26 @@ int DRM(setunique)(struct inode *inode, struct file *filp,
drm_device_t *dev = priv->dev;
drm_unique_t u;
- if (dev->unique_len || dev->unique)
- return -EBUSY;
+ if (dev->unique_len || dev->unique) return -EBUSY;
- if (copy_from_user(&u, (drm_unique_t *)arg, sizeof(u)))
- return -EFAULT;
+ if (copy_from_user(&u, (drm_unique_t *)arg, sizeof(u))) return -EFAULT;
- if (!u.unique_len || u.unique_len > 1024)
- return -EINVAL;
+ if (!u.unique_len || u.unique_len > 1024) return -EINVAL;
dev->unique_len = u.unique_len;
dev->unique = DRM(alloc)(u.unique_len + 1, DRM_MEM_DRIVER);
+ if(!dev->unique) return -ENOMEM;
if (copy_from_user(dev->unique, u.unique, dev->unique_len))
return -EFAULT;
+
dev->unique[dev->unique_len] = '\0';
dev->devname = DRM(alloc)(strlen(dev->name) + strlen(dev->unique) + 2,
DRM_MEM_DRIVER);
+ if(!dev->devname) {
+ DRM(free)(dev->devname, sizeof(*dev->devname), DRM_MEM_DRIVER);
+ return -ENOMEM;
+ }
sprintf(dev->devname, "%s@%s", dev->name, dev->unique);
#ifdef __alpha__
diff --git a/linux/drm_lists.h b/linux/drm_lists.h
index f8dbaaa7..3ad487fd 100644
--- a/linux/drm_lists.h
+++ b/linux/drm_lists.h
@@ -38,9 +38,12 @@ int DRM(waitlist_create)(drm_waitlist_t *bl, int count)
{
if (bl->count) return -EINVAL;
- bl->count = count;
bl->bufs = DRM(alloc)((bl->count + 2) * sizeof(*bl->bufs),
DRM_MEM_BUFLISTS);
+
+ if(!bl->bufs) return -ENOMEM;
+
+ bl->count = count;
bl->rp = bl->bufs;
bl->wp = bl->bufs;
bl->end = &bl->bufs[bl->count+1];
diff --git a/linux/drm_scatter.h b/linux/drm_scatter.h
index a0371074..c1c9f7e8 100644
--- a/linux/drm_scatter.h
+++ b/linux/drm_scatter.h
@@ -93,6 +93,7 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS );
return -ENOMEM;
}
+ memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
entry->virtual = vmalloc_32( pages << PAGE_SHIFT );
if ( !entry->virtual ) {
diff --git a/linux/drm_stub.h b/linux/drm_stub.h
index 6811d6ba..fe8a1bc9 100644
--- a/linux/drm_stub.h
+++ b/linux/drm_stub.h
@@ -84,6 +84,7 @@ static int DRM(stub_getminor)(const char *name, struct file_operations *fops,
if (!DRM(stub_list)) {
DRM(stub_list) = DRM(alloc)(sizeof(*DRM(stub_list))
* DRM_STUB_MAXCARDS, DRM_MEM_STUB);
+ if(!DRM(stub_list)) return -1;
for (i = 0; i < DRM_STUB_MAXCARDS; i++) {
DRM(stub_list)[i].name = NULL;
DRM(stub_list)[i].fops = NULL;
diff --git a/linux/drm_vm.h b/linux/drm_vm.h
index 4db521de..d8e77f79 100644
--- a/linux/drm_vm.h
+++ b/linux/drm_vm.h
@@ -126,7 +126,7 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
{
drm_file_t *priv = vma->vm_file->private_data;
drm_device_t *dev = priv->dev;
- drm_vma_entry_t *pt, *prev;
+ drm_vma_entry_t *pt, *prev, *next;
drm_map_t *map;
drm_map_list_t *r_list;
struct list_head *list;
@@ -146,7 +146,8 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
#endif
down(&dev->struct_sem);
- for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
+ for (pt = dev->vmalist, prev = NULL; pt; pt = next) {
+ next = pt->next;
#if LINUX_VERSION_CODE >= 0x020300
if (pt->vma->vm_private_data == map) found_maps++;
#else
@@ -159,6 +160,8 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
dev->vmalist = pt->next;
}
DRM(free)(pt, sizeof(*pt), DRM_MEM_VMAS);
+ } else {
+ prev = pt;
}
}
/* We were the only map that was found */
@@ -365,6 +368,19 @@ int DRM(mmap_dma)(struct file *filp, struct vm_area_struct *vma)
return 0;
}
+#ifndef DRIVER_GET_MAP_OFS
+#define DRIVER_GET_MAP_OFS() (map->offset)
+#endif
+
+#ifndef DRIVER_GET_REG_OFS
+#ifdef __alpha__
+#define DRIVER_GET_REG_OFS() (dev->hose->dense_mem_base - \
+ dev->hose->mem_space->start)
+#else
+#define DRIVER_GET_REG_OFS() 0
+#endif
+#endif
+
int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
{
drm_file_t *priv = filp->private_data;
@@ -389,10 +405,13 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
for performance, even if the list was a
bit longer. */
list_for_each(list, &dev->maplist->head) {
+ unsigned long off;
+
r_list = (drm_map_list_t *)list;
map = r_list->map;
if (!map) continue;
- if (map->offset == VM_OFFSET(vma)) break;
+ off = DRIVER_GET_MAP_OFS();
+ if (off == VM_OFFSET(vma)) break;
}
if (!map || ((map->flags&_DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
@@ -433,10 +452,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
#endif
vma->vm_flags |= VM_IO; /* not in core dump */
}
-#ifdef __alpha__
- offset = dev->hose->dense_mem_base -
- dev->hose->mem_space->start;
-#endif
+ offset = DRIVER_GET_REG_OFS();
if (remap_page_range(vma->vm_start,
VM_OFFSET(vma) + offset,
vma->vm_end - vma->vm_start,
diff --git a/linux/i810_dma.c b/linux/i810_dma.c
index 75be5d0c..d6933d57 100644
--- a/linux/i810_dma.c
+++ b/linux/i810_dma.c
@@ -379,10 +379,9 @@ static void i810_kernel_lost_context(drm_device_t *dev)
if (ring->space < 0) ring->space += ring->Size;
}
-static int i810_freelist_init(drm_device_t *dev)
+static int i810_freelist_init(drm_device_t *dev, drm_i810_private_t *dev_priv)
{
drm_device_dma_t *dma = dev->dma;
- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
int my_idx = 24;
u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
int i;
@@ -414,7 +413,6 @@ static int i810_dma_initialize(drm_device_t *dev,
{
struct list_head *list;
- dev->dev_private = (void *) dev_priv;
memset(dev_priv, 0, sizeof(drm_i810_private_t));
list_for_each(list, &dev->maplist->head) {
@@ -426,9 +424,26 @@ static int i810_dma_initialize(drm_device_t *dev,
break;
}
}
-
+ if(!dev_priv->sarea_map) {
+ dev->dev_private = (void *)dev_priv;
+ i810_dma_cleanup(dev);
+ DRM_ERROR("can not find sarea!\n");
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->mmio_map, init->mmio_offset );
+ if(!dev_priv->mmio_map) {
+ dev->dev_private = (void *)dev_priv;
+ i810_dma_cleanup(dev);
+ DRM_ERROR("can not find mmio map!\n");
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->buffer_map, init->buffers_offset );
+ if(!dev_priv->buffer_map) {
+ dev->dev_private = (void *)dev_priv;
+ i810_dma_cleanup(dev);
+ DRM_ERROR("can not find dma buffer map!\n");
+ return -EINVAL;
+ }
dev_priv->sarea_priv = (drm_i810_sarea_t *)
((u8 *)dev_priv->sarea_map->handle +
@@ -445,15 +460,16 @@ static int i810_dma_initialize(drm_device_t *dev,
init->ring_start,
init->ring_size);
- dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
-
if (dev_priv->ring.virtual_start == NULL) {
+ dev->dev_private = (void *) dev_priv;
i810_dma_cleanup(dev);
DRM_ERROR("can not ioremap virtual address for"
" ring buffer\n");
return -ENOMEM;
}
+ dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+
dev_priv->w = init->w;
dev_priv->h = init->h;
dev_priv->pitch = init->pitch;
@@ -464,27 +480,30 @@ static int i810_dma_initialize(drm_device_t *dev,
dev_priv->back_di1 = init->back_offset | init->pitch_bits;
dev_priv->zi1 = init->depth_offset | init->pitch_bits;
-
/* Program Hardware Status Page */
dev_priv->hw_status_page = i810_alloc_page(dev);
- memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE);
if(dev_priv->hw_status_page == 0UL) {
+ dev->dev_private = (void *)dev_priv;
i810_dma_cleanup(dev);
DRM_ERROR("Can not allocate hardware status page\n");
return -ENOMEM;
}
+ memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE);
DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page);
I810_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page));
DRM_DEBUG("Enabled hardware status page\n");
/* Now we need to init our freelist */
- if(i810_freelist_init(dev) != 0) {
+ if(i810_freelist_init(dev, dev_priv) != 0) {
+ dev->dev_private = (void *)dev_priv;
i810_dma_cleanup(dev);
DRM_ERROR("Not enough space in the status page for"
" the freelist\n");
return -ENOMEM;
}
+ dev->dev_private = (void *)dev_priv;
+
return 0;
}
diff --git a/linux/i810_drv.c b/linux/i810_drv.c
index d21a19b7..a228cb46 100644
--- a/linux/i810_drv.c
+++ b/linux/i810_drv.c
@@ -41,8 +41,8 @@
#define DRIVER_DESC "Intel i810"
#define DRIVER_DATE "20010616"
-#define DRIVER_MAJOR 2
-#define DRIVER_MINOR 0
+#define DRIVER_MAJOR 1
+#define DRIVER_MINOR 1
#define DRIVER_PATCHLEVEL 0
#define DRIVER_IOCTLS \
diff --git a/linux/mga_dma.c b/linux/mga_dma.c
index 66c9df9f..2a151361 100644
--- a/linux/mga_dma.c
+++ b/linux/mga_dma.c
@@ -292,10 +292,9 @@ static void mga_freelist_print( drm_device_t *dev )
}
#endif
-static int mga_freelist_init( drm_device_t *dev )
+static int mga_freelist_init( drm_device_t *dev, drm_mga_private_t *dev_priv )
{
drm_device_dma_t *dma = dev->dma;
- drm_mga_private_t *dev_priv = dev->dev_private;
drm_buf_t *buf;
drm_mga_buf_priv_t *buf_priv;
drm_mga_freelist_t *entry;
@@ -458,7 +457,6 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
dev_priv = DRM(alloc)( sizeof(drm_mga_private_t), DRM_MEM_DRIVER );
if ( !dev_priv )
return -ENOMEM;
- dev->dev_private = (void *)dev_priv;
memset( dev_priv, 0, sizeof(drm_mga_private_t) );
@@ -497,14 +495,63 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
break;
}
}
+ if(!dev_priv->sarea) {
+ DRM_ERROR( "failed to find sarea!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
+ mga_do_cleanup_dma( dev );
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
+ if(!dev_priv->fb) {
+ DRM_ERROR( "failed to find framebuffer!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
+ mga_do_cleanup_dma( dev );
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
+ if(!dev_priv->mmio) {
+ DRM_ERROR( "failed to find mmio region!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
+ mga_do_cleanup_dma( dev );
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->status, init->status_offset );
+ if(!dev_priv->status) {
+ DRM_ERROR( "failed to find status page!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
+ mga_do_cleanup_dma( dev );
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->warp, init->warp_offset );
+ if(!dev_priv->warp) {
+ DRM_ERROR( "failed to find warp microcode region!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
+ mga_do_cleanup_dma( dev );
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->primary, init->primary_offset );
+ if(!dev_priv->primary) {
+ DRM_ERROR( "failed to find primary dma region!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
+ mga_do_cleanup_dma( dev );
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
+ if(!dev_priv->buffers) {
+ DRM_ERROR( "failed to find dma buffer region!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
+ mga_do_cleanup_dma( dev );
+ return -EINVAL;
+ }
dev_priv->sarea_priv =
(drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle +
@@ -514,16 +561,30 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
DRM_IOREMAP( dev_priv->primary );
DRM_IOREMAP( dev_priv->buffers );
- ret = mga_warp_install_microcode( dev );
+ if(!dev_priv->warp->handle ||
+ !dev_priv->primary->handle ||
+ !dev_priv->buffers->handle ) {
+ DRM_ERROR( "failed to ioremap agp regions!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
+ mga_do_cleanup_dma( dev );
+ return -ENOMEM;
+ }
+
+ ret = mga_warp_install_microcode( dev_priv );
if ( ret < 0 ) {
DRM_ERROR( "failed to install WARP ucode!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
mga_do_cleanup_dma( dev );
return ret;
}
- ret = mga_warp_init( dev );
+ ret = mga_warp_init( dev_priv );
if ( ret < 0 ) {
DRM_ERROR( "failed to init WARP engine!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
mga_do_cleanup_dma( dev );
return ret;
}
@@ -566,12 +627,16 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
dev_priv->sarea_priv->last_frame.head = 0;
dev_priv->sarea_priv->last_frame.wrap = 0;
- if ( mga_freelist_init( dev ) < 0 ) {
+ if ( mga_freelist_init( dev, dev_priv ) < 0 ) {
DRM_ERROR( "could not initialize freelist\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
mga_do_cleanup_dma( dev );
return -ENOMEM;
}
+ /* Make dev_private visable to others. */
+ dev->dev_private = (void *)dev_priv;
return 0;
}
diff --git a/linux/mga_drv.h b/linux/mga_drv.h
index bc70d750..bb3d21b4 100644
--- a/linux/mga_drv.h
+++ b/linux/mga_drv.h
@@ -139,8 +139,8 @@ extern int mga_dma_blit( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg );
/* mga_warp.c */
-extern int mga_warp_install_microcode( drm_device_t *dev );
-extern int mga_warp_init( drm_device_t *dev );
+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() mb()
diff --git a/linux/mga_warp.c b/linux/mga_warp.c
index 5994ab0c..fba691b1 100644
--- a/linux/mga_warp.c
+++ b/linux/mga_warp.c
@@ -160,11 +160,8 @@ static int mga_warp_install_g200_microcode( drm_mga_private_t *dev_priv )
return 0;
}
-int mga_warp_install_microcode( drm_device_t *dev )
+int mga_warp_install_microcode( drm_mga_private_t *dev_priv )
{
- drm_mga_private_t *dev_priv = dev->dev_private;
- DRM_DEBUG( "%s\n", __FUNCTION__ );
-
switch ( dev_priv->chipset ) {
case MGA_CARD_TYPE_G400:
return mga_warp_install_g400_microcode( dev_priv );
@@ -177,11 +174,9 @@ int mga_warp_install_microcode( drm_device_t *dev )
#define WMISC_EXPECTED (MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE)
-int mga_warp_init( drm_device_t *dev )
+int mga_warp_init( drm_mga_private_t *dev_priv )
{
- drm_mga_private_t *dev_priv = dev->dev_private;
u32 wmisc;
- DRM_DEBUG( "%s\n", __FUNCTION__ );
/* FIXME: Get rid of these damned magic numbers...
*/
diff --git a/linux/r128_cce.c b/linux/r128_cce.c
index fbc5fabc..d04473b9 100644
--- a/linux/r128_cce.c
+++ b/linux/r128_cce.c
@@ -314,9 +314,9 @@ static int r128_do_engine_reset( drm_device_t *dev )
return 0;
}
-static void r128_cce_init_ring_buffer( drm_device_t *dev )
+static void r128_cce_init_ring_buffer( drm_device_t *dev,
+ drm_r128_private_t *dev_priv )
{
- drm_r128_private_t *dev_priv = dev->dev_private;
u32 ring_start;
u32 tmp;
@@ -383,17 +383,15 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
dev_priv = DRM(alloc)( sizeof(drm_r128_private_t), DRM_MEM_DRIVER );
if ( dev_priv == NULL )
return -ENOMEM;
- dev->dev_private = (void *)dev_priv;
memset( dev_priv, 0, sizeof(drm_r128_private_t) );
dev_priv->is_pci = init->is_pci;
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 = (void *)dev_priv;
+ r128_do_cleanup_cce( dev );
return -EINVAL;
}
@@ -401,8 +399,8 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
if ( dev_priv->usec_timeout < 1 ||
dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT ) {
DRM_DEBUG( "TIMEOUT problem!\n" );
- DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
- dev->dev_private = NULL;
+ dev->dev_private = (void *)dev_priv;
+ r128_do_cleanup_cce( dev );
return -EINVAL;
}
@@ -421,8 +419,8 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
( init->cce_mode != R128_PM4_64BM_128INDBM ) &&
( init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM ) ) {
DRM_DEBUG( "Bad cce_mode!\n" );
- DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
- dev->dev_private = NULL;
+ dev->dev_private = (void *)dev_priv;
+ r128_do_cleanup_cce( dev );
return -EINVAL;
}
@@ -494,16 +492,58 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
break;
}
}
+ if(!dev_priv->sarea) {
+ DRM_ERROR("could not find sarea!\n");
+ dev->dev_private = (void *)dev_priv;
+ r128_do_cleanup_cce( dev );
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
+ if(!dev_priv->fb) {
+ DRM_ERROR("could not find framebuffer!\n");
+ dev->dev_private = (void *)dev_priv;
+ r128_do_cleanup_cce( dev );
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
+ if(!dev_priv->mmio) {
+ DRM_ERROR("could not find mmio region!\n");
+ dev->dev_private = (void *)dev_priv;
+ r128_do_cleanup_cce( dev );
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->cce_ring, init->ring_offset );
+ if(!dev_priv->cce_ring) {
+ DRM_ERROR("could not find cce ring region!\n");
+ dev->dev_private = (void *)dev_priv;
+ r128_do_cleanup_cce( dev );
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
+ if(!dev_priv->ring_rptr) {
+ DRM_ERROR("could not find ring read pointer!\n");
+ dev->dev_private = (void *)dev_priv;
+ r128_do_cleanup_cce( dev );
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
+ if(!dev_priv->buffers) {
+ DRM_ERROR("could not find dma buffer region!\n");
+ dev->dev_private = (void *)dev_priv;
+ r128_do_cleanup_cce( dev );
+ return -EINVAL;
+ }
if ( !dev_priv->is_pci ) {
DRM_FIND_MAP( dev_priv->agp_textures,
init->agp_textures_offset );
+ if(!dev_priv->agp_textures) {
+ DRM_ERROR("could not find agp texture region!\n");
+ dev->dev_private = (void *)dev_priv;
+ r128_do_cleanup_cce( dev );
+ return -EINVAL;
+ }
}
dev_priv->sarea_priv =
@@ -514,6 +554,14 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
DRM_IOREMAP( dev_priv->cce_ring );
DRM_IOREMAP( dev_priv->ring_rptr );
DRM_IOREMAP( dev_priv->buffers );
+ if(!dev_priv->cce_ring->handle ||
+ !dev_priv->ring_rptr->handle ||
+ !dev_priv->buffers->handle) {
+ DRM_ERROR("Could not ioremap agp regions!\n");
+ dev->dev_private = (void *)dev_priv;
+ r128_do_cleanup_cce( dev );
+ return -ENOMEM;
+ }
} else {
dev_priv->cce_ring->handle =
(void *)dev_priv->cce_ring->offset;
@@ -553,19 +601,20 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
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;
+ dev->dev_private = (void *)dev_priv;
+ r128_do_cleanup_cce( dev );
+ return -ENOMEM;
}
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, dev_priv );
r128_cce_load_microcode( dev_priv );
+
+ dev->dev_private = (void *)dev_priv;
+
r128_do_engine_reset( dev );
return 0;
diff --git a/linux/r128_drv.c b/linux/r128_drv.c
index 4f0bb92b..d4eda6c8 100644
--- a/linux/r128_drv.c
+++ b/linux/r128_drv.c
@@ -41,9 +41,9 @@
#define DRIVER_DESC "ATI Rage 128"
#define DRIVER_DATE "20010405"
-#define DRIVER_MAJOR 3
-#define DRIVER_MINOR 0
-#define DRIVER_PATCHLEVEL 0
+#define DRIVER_MAJOR 2
+#define DRIVER_MINOR 1
+#define DRIVER_PATCHLEVEL 6
#define DRIVER_IOCTLS \
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { r128_cce_buffers, 1, 0 }, \
diff --git a/linux/r128_state.c b/linux/r128_state.c
index 7eafd72d..66af5c45 100644
--- a/linux/r128_state.c
+++ b/linux/r128_state.c
@@ -910,7 +910,7 @@ static int r128_cce_dispatch_write_span( drm_device_t *dev,
return -EFAULT;
}
- buffer = kmalloc( depth->n * sizeof(u32), 0 );
+ buffer = kmalloc( depth->n * sizeof(u32), GFP_KERNEL );
if ( buffer == NULL )
return -ENOMEM;
if ( copy_from_user( buffer, depth->buffer,
@@ -920,7 +920,7 @@ static int r128_cce_dispatch_write_span( drm_device_t *dev,
}
if ( depth->mask ) {
- mask = kmalloc( depth->n * sizeof(u8), 0 );
+ mask = kmalloc( depth->n * sizeof(u8), GFP_KERNEL );
if ( mask == NULL ) {
kfree( buffer );
return -ENOMEM;
@@ -997,11 +997,11 @@ static int r128_cce_dispatch_write_pixels( drm_device_t *dev,
count = depth->n;
- x = kmalloc( count * sizeof(*x), 0 );
+ x = kmalloc( count * sizeof(*x), GFP_KERNEL );
if ( x == NULL ) {
return -ENOMEM;
}
- y = kmalloc( count * sizeof(*y), 0 );
+ y = kmalloc( count * sizeof(*y), GFP_KERNEL );
if ( y == NULL ) {
kfree( x );
return -ENOMEM;
@@ -1017,7 +1017,7 @@ static int r128_cce_dispatch_write_pixels( drm_device_t *dev,
return -EFAULT;
}
- buffer = kmalloc( depth->n * sizeof(u32), 0 );
+ buffer = kmalloc( depth->n * sizeof(u32), GFP_KERNEL );
if ( buffer == NULL ) {
kfree( x );
kfree( y );
@@ -1032,7 +1032,7 @@ static int r128_cce_dispatch_write_pixels( drm_device_t *dev,
}
if ( depth->mask ) {
- mask = kmalloc( depth->n * sizeof(u8), 0 );
+ mask = kmalloc( depth->n * sizeof(u8), GFP_KERNEL );
if ( mask == NULL ) {
kfree( x );
kfree( y );
@@ -1157,11 +1157,11 @@ static int r128_cce_dispatch_read_pixels( drm_device_t *dev,
count = dev_priv->depth_pitch;
}
- x = kmalloc( count * sizeof(*x), 0 );
+ x = kmalloc( count * sizeof(*x), GFP_KERNEL );
if ( x == NULL ) {
return -ENOMEM;
}
- y = kmalloc( count * sizeof(*y), 0 );
+ y = kmalloc( count * sizeof(*y), GFP_KERNEL );
if ( y == NULL ) {
kfree( x );
return -ENOMEM;
diff --git a/linux/radeon_bufs.c b/linux/radeon_bufs.c
deleted file mode 100644
index 9a3093eb..00000000
--- a/linux/radeon_bufs.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/* radeon_bufs.c -- IOCTLs to manage buffers -*- linux-c -*-
- *
- * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Fremont, 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: Kevin E. Martin <martin@valinux.com>
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Jeff Hartmann <jhartmann@valinux.com>
- *
- */
-
-#define __NO_VERSION__
-#include <linux/config.h>
-#include "drmP.h"
-#include "radeon_drv.h"
-#include "linux/un.h"
-
-
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-int radeon_addbufs_agp(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 = dev->agp->base + 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;
-
- for (offset = 0;
- entry->buf_count < count;
- offset += alignment, ++entry->buf_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->address = (void *)(agp_offset + offset);
- buf->next = NULL;
- buf->waiting = 0;
- buf->pending = 0;
- init_waitqueue_head(&buf->dma_wait);
- buf->pid = 0;
-
- buf->dev_priv_size = sizeof(drm_radeon_buf_priv_t);
- buf->dev_private = drm_alloc(sizeof(drm_radeon_buf_priv_t),
- DRM_MEM_BUFS);
- memset(buf->dev_private, 0, buf->dev_priv_size);
-
-#if DRM_DMA_HISTOGRAM
- buf->time_queued = 0;
- buf->time_dispatched = 0;
- buf->time_completed = 0;
- buf->time_freed = 0;
-#endif
-
- byte_count += PAGE_SIZE << page_order;
-
- DRM_DEBUG("buffer %d @ %p\n",
- entry->buf_count, buf->address);
- }
-
- 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 = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
- dma->buflist[i] = &entry->buflist[i - dma->buf_count];
-
- dma->buf_count += entry->buf_count;
- dma->byte_count += byte_count;
-
- 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]);
- }
-
- 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_AGP;
-
- atomic_dec(&dev->buf_alloc);
- return 0;
-}
-#endif
-
-int radeon_addbufs(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_radeon_private_t *dev_priv = dev->dev_private;
- drm_buf_desc_t request;
-
- if (!dev_priv || dev_priv->is_pci) return -EINVAL;
-
- if (copy_from_user(&request, (drm_buf_desc_t *)arg, sizeof(request)))
- return -EFAULT;
-
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
- if (request.flags & _DRM_AGP_BUFFER)
- return radeon_addbufs_agp(inode, filp, cmd, arg);
- else
-#endif
- return -EINVAL;
-}
-
-int radeon_mapbufs(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_radeon_private_t *dev_priv = dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
- int retcode = 0;
- const int zero = 0;
- unsigned long virtual;
- unsigned long address;
- drm_buf_map_t request;
- int i;
-
- if (!dma || !dev_priv || dev_priv->is_pci) return -EINVAL;
-
- DRM_DEBUG("\n");
-
- spin_lock(&dev->count_lock);
- if (atomic_read(&dev->buf_alloc)) {
- spin_unlock(&dev->count_lock);
- return -EBUSY;
- }
- ++dev->buf_use; /* Can't allocate more after this call */
- spin_unlock(&dev->count_lock);
-
- if (copy_from_user(&request, (drm_buf_map_t *)arg, sizeof(request)))
- return -EFAULT;
-
- if (request.count >= dma->buf_count) {
- if (dma->flags & _DRM_DMA_USE_AGP) {
- drm_map_t *map;
-
- map = dev_priv->buffers;
- if (!map) {
- retcode = -EINVAL;
- goto done;
- }
-
- down(&current->mm->mmap_sem);
- virtual = do_mmap(filp, 0, map->size,
- PROT_READ|PROT_WRITE,
- MAP_SHARED,
- (unsigned long)map->offset);
- up(&current->mm->mmap_sem);
- } else {
- down(&current->mm->mmap_sem);
- virtual = do_mmap(filp, 0, dma->byte_count,
- PROT_READ|PROT_WRITE, MAP_SHARED, 0);
- up(&current->mm->mmap_sem);
- }
- if (virtual > -1024UL) {
- /* Real error */
- retcode = (signed long)virtual;
- goto done;
- }
- request.virtual = (void *)virtual;
-
- for (i = 0; i < dma->buf_count; i++) {
- if (copy_to_user(&request.list[i].idx,
- &dma->buflist[i]->idx,
- sizeof(request.list[0].idx))) {
- retcode = -EFAULT;
- goto done;
- }
- if (copy_to_user(&request.list[i].total,
- &dma->buflist[i]->total,
- sizeof(request.list[0].total))) {
- retcode = -EFAULT;
- goto done;
- }
- if (copy_to_user(&request.list[i].used,
- &zero,
- sizeof(zero))) {
- retcode = -EFAULT;
- goto done;
- }
- address = virtual + dma->buflist[i]->offset;
- if (copy_to_user(&request.list[i].address,
- &address,
- sizeof(address))) {
- retcode = -EFAULT;
- goto done;
- }
- }
- }
- done:
- request.count = dma->buf_count;
- DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
-
- if (copy_to_user((drm_buf_map_t *)arg, &request, sizeof(request)))
- return -EFAULT;
-
- return retcode;
-}
diff --git a/linux/radeon_cp.c b/linux/radeon_cp.c
index d8b85949..a7127b2b 100644
--- a/linux/radeon_cp.c
+++ b/linux/radeon_cp.c
@@ -574,12 +574,11 @@ static int radeon_do_engine_reset( drm_device_t *dev )
return 0;
}
-static void radeon_cp_init_ring_buffer( drm_device_t *dev )
+static void radeon_cp_init_ring_buffer( drm_device_t *dev,
+ drm_radeon_private_t *dev_priv )
{
- drm_radeon_private_t *dev_priv = dev->dev_private;
u32 ring_start, cur_read_ptr;
u32 tmp;
- DRM_DEBUG( "%s\n", __FUNCTION__ );
/* Initialize the memory controller */
RADEON_WRITE( RADEON_MC_FB_LOCATION,
@@ -659,7 +658,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER );
if ( dev_priv == NULL )
return -ENOMEM;
- dev->dev_private = (void *)dev_priv;
memset( dev_priv, 0, sizeof(drm_radeon_private_t) );
@@ -670,16 +668,16 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
*/
if ( dev_priv->is_pci ) {
DRM_ERROR( "PCI GART not yet supported for Radeon!\n" );
- DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
- dev->dev_private = NULL;
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
return -EINVAL;
}
#endif
if ( dev_priv->is_pci && !dev->sg ) {
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 = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
return -EINVAL;
}
@@ -687,8 +685,8 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
if ( dev_priv->usec_timeout < 1 ||
dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) {
DRM_DEBUG( "TIMEOUT problem!\n" );
- DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
- dev->dev_private = NULL;
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
return -EINVAL;
}
@@ -705,8 +703,8 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
if ( ( init->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) &&
( init->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) {
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 = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
return -EINVAL;
}
@@ -782,16 +780,58 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
break;
}
}
+ if(!dev_priv->sarea) {
+ DRM_ERROR("could not find sarea!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
+ if(!dev_priv->fb) {
+ DRM_ERROR("could not find framebuffer!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
+ if(!dev_priv->mmio) {
+ DRM_ERROR("could not find mmio region!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->cp_ring, init->ring_offset );
+ if(!dev_priv->cp_ring) {
+ DRM_ERROR("could not find cp ring region!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
+ if(!dev_priv->ring_rptr) {
+ DRM_ERROR("could not find ring read pointer!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ return -EINVAL;
+ }
DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
+ if(!dev_priv->buffers) {
+ DRM_ERROR("could not find dma buffer region!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ return -EINVAL;
+ }
if ( !dev_priv->is_pci ) {
DRM_FIND_MAP( dev_priv->agp_textures,
init->agp_textures_offset );
+ if(!dev_priv->agp_textures) {
+ DRM_ERROR("could not find agp texture region!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ return -EINVAL;
+ }
}
dev_priv->sarea_priv =
@@ -802,6 +842,14 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
DRM_IOREMAP( dev_priv->cp_ring );
DRM_IOREMAP( dev_priv->ring_rptr );
DRM_IOREMAP( dev_priv->buffers );
+ if(!dev_priv->cp_ring->handle ||
+ !dev_priv->ring_rptr->handle ||
+ !dev_priv->buffers->handle) {
+ DRM_ERROR("could not find ioremap agp regions!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ return -EINVAL;
+ }
} else {
dev_priv->cp_ring->handle =
(void *)dev_priv->cp_ring->offset;
@@ -884,10 +932,9 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
dev_priv->phys_pci_gart = DRM(ati_pcigart_init)( dev );
if ( !dev_priv->phys_pci_gart ) {
DRM_ERROR( "failed to init PCI GART!\n" );
- DRM(free)( dev_priv, sizeof(*dev_priv),
- DRM_MEM_DRIVER );
- dev->dev_private = NULL;
- return -EINVAL;
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ return -ENOMEM;
}
/* Turn on PCI GART
*/
@@ -919,13 +966,16 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
}
radeon_cp_load_microcode( dev_priv );
- radeon_cp_init_ring_buffer( dev );
- radeon_do_engine_reset( dev );
+ radeon_cp_init_ring_buffer( dev, dev_priv );
#if ROTATE_BUFS
dev_priv->last_buf = 0;
#endif
+ dev->dev_private = (void *)dev_priv;
+
+ radeon_do_engine_reset( dev );
+
return 0;
}