summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Hartmann <jhartmann@valinux.com>2001-08-07 18:15:10 +0000
committerJeff Hartmann <jhartmann@valinux.com>2001-08-07 18:15:10 +0000
commit51e38d96ead5700c25c4fddd8017dc7992e96f5a (patch)
tree0f0372afa73a701c1be0e9f9b6b65106817d14a6
parent56bd9c207770d41a497f3e8237a1099dd9d4cd91 (diff)
Lots of DRM fixes: added new pieces of template code so the ffb driver can
be ported, rolled back r128 and i810 version bumps so 4.1.0 works with cvs kernel modules, added Config.in and updated Makefile.kernel, incorporated lots of drm fixes inspired by patches sent by Redhat, made DRM(realloc) usage check for NULL allocations, restructure driver init routines to export dev_priv only when initialized and to check for all error conditions.
-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;
}