summaryrefslogtreecommitdiff
path: root/linux-core
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core')
-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
13 files changed, 414 insertions, 268 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 }, \