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 }, \  | 
