diff options
Diffstat (limited to 'linux-core')
-rw-r--r-- | linux-core/Config.in | 16 | ||||
-rw-r--r-- | linux-core/Makefile.kernel | 103 | ||||
-rw-r--r-- | linux-core/drm_bufs.c | 368 | ||||
-rw-r--r-- | linux-core/drm_context.c | 26 | ||||
-rw-r--r-- | linux-core/drm_drv.c | 73 | ||||
-rw-r--r-- | linux-core/drm_fops.c | 2 | ||||
-rw-r--r-- | linux-core/drm_ioctl.c | 15 | ||||
-rw-r--r-- | linux-core/drm_scatter.c | 1 | ||||
-rw-r--r-- | linux-core/drm_stub.c | 1 | ||||
-rw-r--r-- | linux-core/drm_vm.c | 30 | ||||
-rw-r--r-- | linux-core/i810_dma.c | 37 | ||||
-rw-r--r-- | linux-core/i810_drv.c | 4 | ||||
-rw-r--r-- | linux-core/r128_drv.c | 6 |
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 }, \ |