diff options
author | Jose Fonseca <jrfonseca@users.sourceforge.net> | 2003-07-01 18:56:57 +0000 |
---|---|---|
committer | Jose Fonseca <jrfonseca@users.sourceforge.net> | 2003-07-01 18:56:57 +0000 |
commit | a30e4805531b02247b2ce0ae3a20919244ec3cad (patch) | |
tree | c8a2cdabd8ddcb756c73c7e3c3fcab78db1abd1a | |
parent | d0a34c7d9601d938a40c36ba6279b2e59494f47a (diff) |
Creation of PCI, AGP and SG buffer pools. Make buffers ioctls use these (to
keep backwards compatability). Move some of the templates into proper C
files which will be shared by all modules. (This changes are not
complete and everythin is severily broken ATM).
-rw-r--r-- | linux-core/Makefile.kernel | 37 | ||||
-rw-r--r-- | linux-core/ati_pcigart.c | 180 | ||||
-rw-r--r-- | linux-core/drmP.h | 8 | ||||
-rw-r--r-- | linux-core/drm_bufs.c | 64 | ||||
-rw-r--r-- | linux-core/drm_dma.c | 3 | ||||
-rw-r--r-- | linux-core/drm_memory.h | 54 | ||||
-rw-r--r-- | linux/Makefile.kernel | 37 | ||||
-rw-r--r-- | linux/Makefile.linux | 2 | ||||
-rw-r--r-- | linux/ati_pcigart.h | 180 | ||||
-rw-r--r-- | linux/drmP.h | 8 | ||||
-rw-r--r-- | linux/drm_agp.c (renamed from linux/drm_agp_tmp.h) | 80 | ||||
-rw-r--r-- | linux/drm_agp.h | 40 | ||||
-rw-r--r-- | linux/drm_bufs.c (renamed from linux/drm_bufs_tmp.h) | 1187 | ||||
-rw-r--r-- | linux/drm_bufs.h | 64 | ||||
-rw-r--r-- | linux/drm_dma.h | 3 | ||||
-rw-r--r-- | linux/drm_mem.c (renamed from linux/drm_memory_tmp.h) | 210 | ||||
-rw-r--r-- | linux/drm_memory.h | 54 | ||||
-rw-r--r-- | linux/drm_pci.c (renamed from linux/drm_pci_tmp.h) | 56 | ||||
-rw-r--r-- | linux/drm_sg.c (renamed from linux/drm_sg_tmp.h) | 44 | ||||
-rw-r--r-- | linux/drm_sg.h | 10 |
20 files changed, 916 insertions, 1405 deletions
diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index 5f79e430a..d4286a348 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -7,6 +7,7 @@ # $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.kernel,v 1.17 2003/04/12 17:18:17 dawes Exp $ # +drm-objs := drm_pci.o drm_agp.o drm_sg.o drm_mem.o drm_bufs.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 r128_irq.o @@ -51,31 +52,31 @@ include $(TOPDIR)/Rules.make endif ifeq ($(BELOW25),y) -gamma.o: $(gamma-objs) $(lib) - $(LD) -r -o $@ $(gamma-objs) $(lib) +gamma.o: $(gamma-objs) $(drm-objs) $(lib) + $(LD) -r -o $@ $(gamma-objs) $(drm-objs) $(lib) -tdfx.o: $(tdfx-objs) $(lib) - $(LD) -r -o $@ $(tdfx-objs) $(lib) +tdfx.o: $(tdfx-objs) $(drm-objs) $(lib) + $(LD) -r -o $@ $(tdfx-objs) $(drm-objs) $(lib) -mga.o: $(mga-objs) $(lib) - $(LD) -r -o $@ $(mga-objs) $(lib) +mga.o: $(mga-objs) $(drm-objs) $(lib) + $(LD) -r -o $@ $(mga-objs) $(drm-objs) $(lib) -i810.o: $(i810-objs) $(lib) - $(LD) -r -o $@ $(i810-objs) $(lib) +i810.o: $(i810-objs) $(drm-objs) $(lib) + $(LD) -r -o $@ $(i810-objs) $(drm-objs) $(lib) -i830.o: $(i830-objs) $(lib) - $(LD) -r -o $@ $(i830-objs) $(lib) +i830.o: $(i830-objs) $(drm-objs) $(lib) + $(LD) -r -o $@ $(i830-objs) $(drm-objs) $(lib) -r128.o: $(r128-objs) $(lib) - $(LD) -r -o $@ $(r128-objs) $(lib) +r128.o: $(r128-objs) $(drm-objs) $(lib) + $(LD) -r -o $@ $(r128-objs) $(drm-objs) $(lib) -radeon.o: $(radeon-objs) $(lib) - $(LD) -r -o $@ $(radeon-objs) $(lib) +radeon.o: $(radeon-objs) $(drm-objs) $(lib) + $(LD) -r -o $@ $(radeon-objs) $(drm-objs) $(lib) -sis.o: $(sis-objs) $(lib) - $(LD) -r -o $@ $(sis-objs) $(lib) +sis.o: $(sis-objs) $(drm-objs) $(lib) + $(LD) -r -o $@ $(sis-objs) $(drm-objs) $(lib) -ffb.o: $(ffb-objs) $(lib) - $(LD) -r -o $@ $(ffb-objs) $(lib) +ffb.o: $(ffb-objs) $(drm-objs) $(lib) + $(LD) -r -o $@ $(ffb-objs) $(drm-objs) $(lib) endif diff --git a/linux-core/ati_pcigart.c b/linux-core/ati_pcigart.c index 42233ff9b..d11261215 100644 --- a/linux-core/ati_pcigart.c +++ b/linux-core/ati_pcigart.c @@ -31,177 +31,21 @@ * DEALINGS IN THE SOFTWARE. */ -#define __NO_VERSION__ -#include "drmP.h" +#ifndef _DRM_ATI_PCIGART_H_ +#define _DRM_ATI_PCIGART_H_ -#if PAGE_SIZE == 65536 -# define ATI_PCIGART_TABLE_ORDER 0 -# define ATI_PCIGART_TABLE_PAGES (1 << 0) -#elif PAGE_SIZE == 16384 -# define ATI_PCIGART_TABLE_ORDER 1 -# define ATI_PCIGART_TABLE_PAGES (1 << 1) -#elif PAGE_SIZE == 8192 -# define ATI_PCIGART_TABLE_ORDER 2 -# define ATI_PCIGART_TABLE_PAGES (1 << 2) -#elif PAGE_SIZE == 4096 -# define ATI_PCIGART_TABLE_ORDER 3 -# define ATI_PCIGART_TABLE_PAGES (1 << 3) -#else -# error - PAGE_SIZE not 64K, 16K, 8K or 4K -#endif -# define ATI_MAX_PCIGART_PAGES 8192 /**< 32 MB aperture, 4K pages */ -# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ +/** \name Prototypes */ +/*@{*/ -static unsigned long DRM(ati_alloc_pcigart_table)( void ) -{ - unsigned long address; - struct page *page; - int i; - DRM_DEBUG( "%s\n", __FUNCTION__ ); +extern int drm_ati_pcigart_init(drm_device_t *dev, + unsigned long *addr, + dma_addr_t *bus_addr); +extern int drm_ati_pcigart_cleanup(drm_device_t *dev, + unsigned long addr, + dma_addr_t bus_addr); - address = __get_free_pages( GFP_KERNEL, ATI_PCIGART_TABLE_ORDER ); - if ( address == 0UL ) { - return 0; - } +/*@}*/ - page = virt_to_page( address ); - for ( i = 0 ; i < ATI_PCIGART_TABLE_PAGES ; i++, page++ ) { - atomic_inc( &page->count ); - SetPageReserved( page ); - } - - DRM_DEBUG( "%s: returning 0x%08lx\n", __FUNCTION__, address ); - return address; -} - -static void DRM(ati_free_pcigart_table)( unsigned long address ) -{ - struct page *page; - int i; - DRM_DEBUG( "%s\n", __FUNCTION__ ); - - page = virt_to_page( address ); - - for ( i = 0 ; i < ATI_PCIGART_TABLE_PAGES ; i++, page++ ) { - atomic_dec( &page->count ); - ClearPageReserved( page ); - } - - free_pages( address, ATI_PCIGART_TABLE_ORDER ); -} - -int DRM(ati_pcigart_init)( drm_device_t *dev, - unsigned long *addr, - dma_addr_t *bus_addr) -{ - drm_sg_mem_t *entry = dev->sg; - unsigned long address = 0; - unsigned long pages; - u32 *pci_gart, page_base, bus_address = 0; - int i, j, ret = 0; - - if ( !entry ) { - DRM_ERROR( "no scatter/gather memory!\n" ); - goto done; - } - - address = DRM(ati_alloc_pcigart_table)(); - if ( !address ) { - DRM_ERROR( "cannot allocate PCI GART page!\n" ); - goto done; - } - - if ( !dev->pdev ) { - DRM_ERROR( "PCI device unknown!\n" ); - goto done; - } - - bus_address = pci_map_single(dev->pdev, (void *)address, - ATI_PCIGART_TABLE_PAGES * PAGE_SIZE, - PCI_DMA_TODEVICE); - if (bus_address == 0) { - DRM_ERROR( "unable to map PCIGART pages!\n" ); - DRM(ati_free_pcigart_table)( address ); - address = 0; - goto done; - } - - pci_gart = (u32 *)address; - - pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES ) - ? entry->pages : ATI_MAX_PCIGART_PAGES; - - memset( pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32) ); - - for ( i = 0 ; i < pages ; i++ ) { - /* we need to support large memory configurations */ - entry->busaddr[i] = pci_map_single(dev->pdev, - page_address( entry->pagelist[i] ), - PAGE_SIZE, - PCI_DMA_TODEVICE); - if (entry->busaddr[i] == 0) { - DRM_ERROR( "unable to map PCIGART pages!\n" ); - DRM(ati_pcigart_cleanup)( dev, address, bus_address ); - address = 0; - bus_address = 0; - goto done; - } - page_base = (u32) entry->busaddr[i]; - - for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { - *pci_gart++ = cpu_to_le32( page_base ); - page_base += ATI_PCIGART_PAGE_SIZE; - } - } - - ret = 1; - -#if defined(__i386__) || defined(__x86_64__) - asm volatile ( "wbinvd" ::: "memory" ); -#else - mb(); -#endif - -done: - *addr = address; - *bus_addr = bus_address; - return ret; -} - -int DRM(ati_pcigart_cleanup)( drm_device_t *dev, - unsigned long addr, - dma_addr_t bus_addr) -{ - drm_sg_mem_t *entry = dev->sg; - unsigned long pages; - int i; - - /* we need to support large memory configurations */ - if ( !entry ) { - DRM_ERROR( "no scatter/gather memory!\n" ); - return 0; - } - - if ( bus_addr ) { - pci_unmap_single(dev->pdev, bus_addr, - ATI_PCIGART_TABLE_PAGES * PAGE_SIZE, - PCI_DMA_TODEVICE); - - pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES ) - ? entry->pages : ATI_MAX_PCIGART_PAGES; - - for ( i = 0 ; i < pages ; i++ ) { - if ( !entry->busaddr[i] ) break; - pci_unmap_single(dev->pdev, entry->busaddr[i], - PAGE_SIZE, PCI_DMA_TODEVICE); - } - } - - if ( addr ) { - DRM(ati_free_pcigart_table)( addr ); - } - - return 1; -} +#endif /* !_DRM_ATI_PCIGART_H_ */ diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 4cd5844c2..d2392daaa 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -641,14 +641,6 @@ extern int DRM(proc_cleanup)(int minor, struct proc_dir_entry *root, struct proc_dir_entry *dev_root); - /* ATI PCIGART support (ati_pcigart.h) */ -extern int DRM(ati_pcigart_init)(drm_device_t *dev, - unsigned long *addr, - dma_addr_t *bus_addr); -extern int DRM(ati_pcigart_cleanup)(drm_device_t *dev, - unsigned long addr, - dma_addr_t bus_addr); - /*@}*/ #endif /* __KERNEL__ */ diff --git a/linux-core/drm_bufs.c b/linux-core/drm_bufs.c index 58b7e0e1d..c35c01312 100644 --- a/linux-core/drm_bufs.c +++ b/linux-core/drm_bufs.c @@ -1,23 +1,10 @@ /** * \file drm_bufs.h - * Buffer management. + * DMA buffers management. * * \author Rickard E. (Rik) Faith <faith@valinux.com> * \author Gareth Hughes <gareth@valinux.com> * \author José Fonseca <jrfonseca@tungstengraphics.com> - * - * \todo The current buffer management system assumes too much and is severily - * limited: - * - It expects to all buffers to be used by clients, and has little provisions - * for private buffers (such as ring buffers, primary DMA buffers, etc.) This - * is currently overcomed by allocating these buffers directly in AGP memory - * when available, or by allocating a pool with a single buffer and with a - * size different of the regular client buffers. - * - It doesn't allow to be two different pools with the same log2 of the - * buffers size making impossible, e.g., to have to pools of buffers: one - * private and one public. - * - The high/low water mark is hardly used and the freelist should be - * redesigned to be more useful for all drivers. */ /* @@ -59,7 +46,7 @@ typedef struct drm_pool drm_pool_t; /** * A buffer of the DMA buffer pool. * - * \sa drm_pool. + * This structure holds individual buffer information. See also drm_pool. */ struct drm_pool_buffer { void * cpuaddr; /**< kernel virtual address */ @@ -69,7 +56,14 @@ struct drm_pool_buffer { /** * DMA buffer pool. * - * \sa drm_pool_buffer. + * This structure stores information about an homogeneous pool of buffers. See + * also drm_pool_buffer. + * + * It only provides the basic information. This structure can be extended by + * composition. See drm_pool_pci, drm_pool_agp, and drm_pool_sg for examples. + * + * See drm_freelist2 for a convinient and extensible way to manage a buffer + * pool. */ struct drm_pool { size_t count; /**< number of buffers */ @@ -86,11 +80,11 @@ struct drm_pool { /** \name Free-list management */ /*@{*/ -typedef struct drm_freelist2_entrys drm_freelist2_entrys_t; +typedef struct drm_freelist2_entry drm_freelist2_entry_t; typedef struct drm_freelist2 drm_freelist2_t; /** - * An entrys in a freelist. + * An entryin a freelist. * * This structure can be extended by passing to drm_freelist2_init a stride * value greater than the size of this structure. @@ -100,7 +94,7 @@ typedef struct drm_freelist2 drm_freelist2_t; * \author Based on Leif Delgass's original freelist code for the Mach64 * driver. */ -struct drm_freelist2_entrys { +struct drm_freelist2_entry { struct list_head list; /**< Linux list */ drm_pool_buffer_t * buffer; /**< referred DMA buffer */ @@ -154,7 +148,7 @@ struct drm_freelist2 { /** * Stamp of the last processed buffer. * - * \sa drm_free_list2_entrys::stamp. + * \sa drm_free_list2_entry::stamp. */ unsigned long last_stamp; @@ -168,6 +162,7 @@ struct drm_freelist2 { /*@}*/ +#if 0 /** \name Deprecated structure */ /*@{*/ @@ -253,6 +248,35 @@ typedef struct drm_buf_entry { } drm_buf_entry_t; /*@}*/ +#endif + +/** + * Backward compatability buffer pools used by the addbufs_ioctl() and friends. + * + * There is one of these for each buffer size in log2. Note that there can't be + * two different pools with the same log2 of the buffers size. + */ +typedef struct drm_buf_entry { + drm_pool_t * pool; /**< the pool */ + int seg_count; + int page_order; + unsigned long * seglist; +} drm_buf_entry_t; + + + +/** + * Device buffer related data. + */ +typedef struct drm_bufs_data_t { + /** buffers, grouped by their size order for backwards compatability */ + drm_buf_entry_t bufs[DRM_MAX_ORDER + 1]; + enum { + _DRM_DMA_USE_AGP = 0x01, + _DRM_DMA_USE_SG = 0x02 + } flags; +} ; + /** \name Prototypes */ diff --git a/linux-core/drm_dma.c b/linux-core/drm_dma.c index 14d5043dc..e934f126d 100644 --- a/linux-core/drm_dma.c +++ b/linux-core/drm_dma.c @@ -57,10 +57,11 @@ typedef struct drm_queue { * DMA data. */ typedef struct drm_device_dma { - +#if 0 drm_buf_entry_t bufs[DRM_MAX_ORDER+1]; /**< buffers, grouped by their size order */ int buf_count; /**< total number of buffers */ drm_buf_t **buflist; /**< Vector of pointers into drm_device_dma::bufs */ +#endif int seg_count; int page_count; /**< number of pages */ unsigned long *pagelist; /**< page list */ diff --git a/linux-core/drm_memory.h b/linux-core/drm_memory.h deleted file mode 100644 index 5ccaa5b05..000000000 --- a/linux-core/drm_memory.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * \file drm_memory.h - * Memory management wrappers for DRM - * - * \author Rickard E. (Rik) Faith <faith@valinux.com> - * \author Gareth Hughes <gareth@valinux.com> - */ - -/* - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, 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 - * VA LINUX SYSTEMS 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. - */ - - -#ifndef _DRM_MEMORY_H_ -#define _DRM_MEMORY_H_ - - -/** \name Prototypes */ -/*@{*/ - -extern void *DRM(alloc)(size_t size, int area); -extern void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size, int area); -extern void DRM(free)(void *pt, size_t size, int area); -extern unsigned long DRM(alloc_pages)(int order, int area); -extern void DRM(free_pages)(unsigned long address, int order, int area); -extern void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev); -extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev); -extern void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev); - -/*@}*/ - - -#endif /* !_DRM_MEMORY_H_ */ diff --git a/linux/Makefile.kernel b/linux/Makefile.kernel index 5f79e430a..d4286a348 100644 --- a/linux/Makefile.kernel +++ b/linux/Makefile.kernel @@ -7,6 +7,7 @@ # $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.kernel,v 1.17 2003/04/12 17:18:17 dawes Exp $ # +drm-objs := drm_pci.o drm_agp.o drm_sg.o drm_mem.o drm_bufs.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 r128_irq.o @@ -51,31 +52,31 @@ include $(TOPDIR)/Rules.make endif ifeq ($(BELOW25),y) -gamma.o: $(gamma-objs) $(lib) - $(LD) -r -o $@ $(gamma-objs) $(lib) +gamma.o: $(gamma-objs) $(drm-objs) $(lib) + $(LD) -r -o $@ $(gamma-objs) $(drm-objs) $(lib) -tdfx.o: $(tdfx-objs) $(lib) - $(LD) -r -o $@ $(tdfx-objs) $(lib) +tdfx.o: $(tdfx-objs) $(drm-objs) $(lib) + $(LD) -r -o $@ $(tdfx-objs) $(drm-objs) $(lib) -mga.o: $(mga-objs) $(lib) - $(LD) -r -o $@ $(mga-objs) $(lib) +mga.o: $(mga-objs) $(drm-objs) $(lib) + $(LD) -r -o $@ $(mga-objs) $(drm-objs) $(lib) -i810.o: $(i810-objs) $(lib) - $(LD) -r -o $@ $(i810-objs) $(lib) +i810.o: $(i810-objs) $(drm-objs) $(lib) + $(LD) -r -o $@ $(i810-objs) $(drm-objs) $(lib) -i830.o: $(i830-objs) $(lib) - $(LD) -r -o $@ $(i830-objs) $(lib) +i830.o: $(i830-objs) $(drm-objs) $(lib) + $(LD) -r -o $@ $(i830-objs) $(drm-objs) $(lib) -r128.o: $(r128-objs) $(lib) - $(LD) -r -o $@ $(r128-objs) $(lib) +r128.o: $(r128-objs) $(drm-objs) $(lib) + $(LD) -r -o $@ $(r128-objs) $(drm-objs) $(lib) -radeon.o: $(radeon-objs) $(lib) - $(LD) -r -o $@ $(radeon-objs) $(lib) +radeon.o: $(radeon-objs) $(drm-objs) $(lib) + $(LD) -r -o $@ $(radeon-objs) $(drm-objs) $(lib) -sis.o: $(sis-objs) $(lib) - $(LD) -r -o $@ $(sis-objs) $(lib) +sis.o: $(sis-objs) $(drm-objs) $(lib) + $(LD) -r -o $@ $(sis-objs) $(drm-objs) $(lib) -ffb.o: $(ffb-objs) $(lib) - $(LD) -r -o $@ $(ffb-objs) $(lib) +ffb.o: $(ffb-objs) $(drm-objs) $(lib) + $(LD) -r -o $@ $(ffb-objs) $(drm-objs) $(lib) endif diff --git a/linux/Makefile.linux b/linux/Makefile.linux index c3451399f..a6d574cf2 100644 --- a/linux/Makefile.linux +++ b/linux/Makefile.linux @@ -44,7 +44,7 @@ endif MACHINE := $(shell uname -m) # Modules for all architectures -MODULE_LIST := gamma.o tdfx.o r128.o radeon.o mga.o #sis.o +MODULE_LIST := tdfx.o r128.o radeon.o mga.o #sis.o gamma.o # Modules only for ix86 architectures ifneq (,$(findstring 86,$(MACHINE))) diff --git a/linux/ati_pcigart.h b/linux/ati_pcigart.h index 42233ff9b..d11261215 100644 --- a/linux/ati_pcigart.h +++ b/linux/ati_pcigart.h @@ -31,177 +31,21 @@ * DEALINGS IN THE SOFTWARE. */ -#define __NO_VERSION__ -#include "drmP.h" +#ifndef _DRM_ATI_PCIGART_H_ +#define _DRM_ATI_PCIGART_H_ -#if PAGE_SIZE == 65536 -# define ATI_PCIGART_TABLE_ORDER 0 -# define ATI_PCIGART_TABLE_PAGES (1 << 0) -#elif PAGE_SIZE == 16384 -# define ATI_PCIGART_TABLE_ORDER 1 -# define ATI_PCIGART_TABLE_PAGES (1 << 1) -#elif PAGE_SIZE == 8192 -# define ATI_PCIGART_TABLE_ORDER 2 -# define ATI_PCIGART_TABLE_PAGES (1 << 2) -#elif PAGE_SIZE == 4096 -# define ATI_PCIGART_TABLE_ORDER 3 -# define ATI_PCIGART_TABLE_PAGES (1 << 3) -#else -# error - PAGE_SIZE not 64K, 16K, 8K or 4K -#endif -# define ATI_MAX_PCIGART_PAGES 8192 /**< 32 MB aperture, 4K pages */ -# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ +/** \name Prototypes */ +/*@{*/ -static unsigned long DRM(ati_alloc_pcigart_table)( void ) -{ - unsigned long address; - struct page *page; - int i; - DRM_DEBUG( "%s\n", __FUNCTION__ ); +extern int drm_ati_pcigart_init(drm_device_t *dev, + unsigned long *addr, + dma_addr_t *bus_addr); +extern int drm_ati_pcigart_cleanup(drm_device_t *dev, + unsigned long addr, + dma_addr_t bus_addr); - address = __get_free_pages( GFP_KERNEL, ATI_PCIGART_TABLE_ORDER ); - if ( address == 0UL ) { - return 0; - } +/*@}*/ - page = virt_to_page( address ); - for ( i = 0 ; i < ATI_PCIGART_TABLE_PAGES ; i++, page++ ) { - atomic_inc( &page->count ); - SetPageReserved( page ); - } - - DRM_DEBUG( "%s: returning 0x%08lx\n", __FUNCTION__, address ); - return address; -} - -static void DRM(ati_free_pcigart_table)( unsigned long address ) -{ - struct page *page; - int i; - DRM_DEBUG( "%s\n", __FUNCTION__ ); - - page = virt_to_page( address ); - - for ( i = 0 ; i < ATI_PCIGART_TABLE_PAGES ; i++, page++ ) { - atomic_dec( &page->count ); - ClearPageReserved( page ); - } - - free_pages( address, ATI_PCIGART_TABLE_ORDER ); -} - -int DRM(ati_pcigart_init)( drm_device_t *dev, - unsigned long *addr, - dma_addr_t *bus_addr) -{ - drm_sg_mem_t *entry = dev->sg; - unsigned long address = 0; - unsigned long pages; - u32 *pci_gart, page_base, bus_address = 0; - int i, j, ret = 0; - - if ( !entry ) { - DRM_ERROR( "no scatter/gather memory!\n" ); - goto done; - } - - address = DRM(ati_alloc_pcigart_table)(); - if ( !address ) { - DRM_ERROR( "cannot allocate PCI GART page!\n" ); - goto done; - } - - if ( !dev->pdev ) { - DRM_ERROR( "PCI device unknown!\n" ); - goto done; - } - - bus_address = pci_map_single(dev->pdev, (void *)address, - ATI_PCIGART_TABLE_PAGES * PAGE_SIZE, - PCI_DMA_TODEVICE); - if (bus_address == 0) { - DRM_ERROR( "unable to map PCIGART pages!\n" ); - DRM(ati_free_pcigart_table)( address ); - address = 0; - goto done; - } - - pci_gart = (u32 *)address; - - pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES ) - ? entry->pages : ATI_MAX_PCIGART_PAGES; - - memset( pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32) ); - - for ( i = 0 ; i < pages ; i++ ) { - /* we need to support large memory configurations */ - entry->busaddr[i] = pci_map_single(dev->pdev, - page_address( entry->pagelist[i] ), - PAGE_SIZE, - PCI_DMA_TODEVICE); - if (entry->busaddr[i] == 0) { - DRM_ERROR( "unable to map PCIGART pages!\n" ); - DRM(ati_pcigart_cleanup)( dev, address, bus_address ); - address = 0; - bus_address = 0; - goto done; - } - page_base = (u32) entry->busaddr[i]; - - for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { - *pci_gart++ = cpu_to_le32( page_base ); - page_base += ATI_PCIGART_PAGE_SIZE; - } - } - - ret = 1; - -#if defined(__i386__) || defined(__x86_64__) - asm volatile ( "wbinvd" ::: "memory" ); -#else - mb(); -#endif - -done: - *addr = address; - *bus_addr = bus_address; - return ret; -} - -int DRM(ati_pcigart_cleanup)( drm_device_t *dev, - unsigned long addr, - dma_addr_t bus_addr) -{ - drm_sg_mem_t *entry = dev->sg; - unsigned long pages; - int i; - - /* we need to support large memory configurations */ - if ( !entry ) { - DRM_ERROR( "no scatter/gather memory!\n" ); - return 0; - } - - if ( bus_addr ) { - pci_unmap_single(dev->pdev, bus_addr, - ATI_PCIGART_TABLE_PAGES * PAGE_SIZE, - PCI_DMA_TODEVICE); - - pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES ) - ? entry->pages : ATI_MAX_PCIGART_PAGES; - - for ( i = 0 ; i < pages ; i++ ) { - if ( !entry->busaddr[i] ) break; - pci_unmap_single(dev->pdev, entry->busaddr[i], - PAGE_SIZE, PCI_DMA_TODEVICE); - } - } - - if ( addr ) { - DRM(ati_free_pcigart_table)( addr ); - } - - return 1; -} +#endif /* !_DRM_ATI_PCIGART_H_ */ diff --git a/linux/drmP.h b/linux/drmP.h index 4cd5844c2..d2392daaa 100644 --- a/linux/drmP.h +++ b/linux/drmP.h @@ -641,14 +641,6 @@ extern int DRM(proc_cleanup)(int minor, struct proc_dir_entry *root, struct proc_dir_entry *dev_root); - /* ATI PCIGART support (ati_pcigart.h) */ -extern int DRM(ati_pcigart_init)(drm_device_t *dev, - unsigned long *addr, - dma_addr_t *bus_addr); -extern int DRM(ati_pcigart_cleanup)(drm_device_t *dev, - unsigned long addr, - dma_addr_t bus_addr); - /*@}*/ #endif /* __KERNEL__ */ diff --git a/linux/drm_agp_tmp.h b/linux/drm_agp.c index e4da3a737..a5e34ad49 100644 --- a/linux/drm_agp_tmp.h +++ b/linux/drm_agp.c @@ -61,7 +61,7 @@ static unsigned drm_agp_refcount = 0; /** * Acquire the AGP device. */ -int DRM(agp_acquire)(void) +int drm_agp_acquire(void) { if (!drm_agp || !drm_agp->acquire) return -EINVAL; @@ -71,7 +71,7 @@ int DRM(agp_acquire)(void) /** * Release the AGP device. */ -void DRM(agp_release)(void) +void drm_agp_release(void) { if (!drm_agp || !drm_agp->release) return; @@ -81,7 +81,7 @@ void DRM(agp_release)(void) /** * Enable the AGP bus. */ -void DRM(agp_enable)(unsigned long mode) +void drm_agp_enable(unsigned long mode) { if (!drm_agp || !drm_agp->enable) return; @@ -91,7 +91,7 @@ void DRM(agp_enable)(unsigned long mode) /** * Allocate AGP memory. */ -agp_memory *DRM(agp_alloc)(size_t pages, u32 type) +agp_memory *drm_agp_alloc(size_t pages, u32 type) { if (!drm_agp || !drm_agp->allocate_memory) return NULL; @@ -104,7 +104,7 @@ agp_memory *DRM(agp_alloc)(size_t pages, u32 type) * Not meant to be called directly. Use agp_free() instead, which can provide * some debugging features. */ -int DRM(agp_free)(agp_memory *handle) +int drm_agp_free(agp_memory *handle) { if (!handle || !drm_agp || !drm_agp->free_memory) return 0; @@ -118,7 +118,7 @@ int DRM(agp_free)(agp_memory *handle) * Not meant to be called directly. Use agp_bind() instead, which can provide * some debugging features. */ -int DRM(agp_bind)(agp_memory *handle, off_t start) +int drm_agp_bind(agp_memory *handle, off_t start) { if (!handle || !drm_agp || !drm_agp->bind_memory) return -EINVAL; @@ -131,7 +131,7 @@ int DRM(agp_bind)(agp_memory *handle, off_t start) * Not meant to be called directly. Use agp_unbind() instead, which can provide * some debugging features. */ -int DRM(agp_unbind)(agp_memory *handle) +int drm_agp_unbind(agp_memory *handle) { if (!handle || !drm_agp || !drm_agp->unbind_memory) return -EINVAL; @@ -157,7 +157,7 @@ int DRM(agp_unbind)(agp_memory *handle) * Verifies the AGP device hasn't been acquired before and calls * drm_acquire(). */ -int DRM(agp_acquire_ioctl)(struct inode *inode, struct file *filp, +int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; @@ -166,7 +166,7 @@ int DRM(agp_acquire_ioctl)(struct inode *inode, struct file *filp, if (!dev->agp || dev->agp->acquired || !drm_agp->acquire) return -EINVAL; - if ((retcode = DRM(agp_acquire)())) return retcode; + if ((retcode = drm_agp_acquire())) return retcode; dev->agp->acquired = 1; return 0; } @@ -182,7 +182,7 @@ int DRM(agp_acquire_ioctl)(struct inode *inode, struct file *filp, * * Verifies the AGP device has been acquired and calls drm_agp->release(). */ -int DRM(agp_release_ioctl)(struct inode *inode, struct file *filp, +int drm_agp_release_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; @@ -208,7 +208,7 @@ int DRM(agp_release_ioctl)(struct inode *inode, struct file *filp, * Verifies the AGP device has been initialized and acquired and fills in the * drm_agp_info structure with the information in drm_agp_head::agp_info. */ -int DRM(agp_info_ioctl)(struct inode *inode, struct file *filp, +int drm_agp_info_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; @@ -247,7 +247,7 @@ int DRM(agp_info_ioctl)(struct inode *inode, struct file *filp, * Verifies the AGP device has been acquired, and calls * agp_enable(). */ -int DRM(agp_enable_ioctl)(struct inode *inode, struct file *filp, +int drm_agp_enable_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; @@ -261,7 +261,7 @@ int DRM(agp_enable_ioctl)(struct inode *inode, struct file *filp, return -EFAULT; dev->agp->mode = mode.mode; - DRM(agp_enable)(mode.mode); + drm_agp_enable(mode.mode); dev->agp->base = dev->agp->agp_info.aper_base; dev->agp->enabled = 1; return 0; @@ -279,7 +279,7 @@ int DRM(agp_enable_ioctl)(struct inode *inode, struct file *filp, * Verifies the AGP device is present and has been acquired, allocates the * memory via agp_alloc() and creates a drm_agp_mem entry for it. */ -int DRM(agp_alloc_ioctl)(struct inode *inode, struct file *filp, +int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; @@ -293,7 +293,7 @@ int DRM(agp_alloc_ioctl)(struct inode *inode, struct file *filp, if (!dev->agp || !dev->agp->acquired) return -EINVAL; if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request))) return -EFAULT; - if (!(entry = DRM(alloc)(sizeof(*entry), DRM_MEM_AGPLISTS))) + if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS))) return -ENOMEM; memset(entry, 0, sizeof(*entry)); @@ -301,8 +301,8 @@ int DRM(agp_alloc_ioctl)(struct inode *inode, struct file *filp, pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE; type = (u32) request.type; - if (!(memory = DRM(agp_alloc)(pages, type))) { - DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS); + if (!(memory = drm_agp_alloc(pages, type))) { + drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); return -ENOMEM; } @@ -321,8 +321,8 @@ int DRM(agp_alloc_ioctl)(struct inode *inode, struct file *filp, if (copy_to_user((drm_agp_buffer_t *)arg, &request, sizeof(request))) { dev->agp->memory = entry->next; dev->agp->memory->prev = NULL; - DRM(agp_free)(memory); - DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS); + drm_agp_free(memory); + drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); return -EFAULT; } return 0; @@ -337,7 +337,7 @@ int DRM(agp_alloc_ioctl)(struct inode *inode, struct file *filp, * * Walks through drm_agp_head::memory until finding a matching handle. */ -static drm_agp_mem_t *DRM(agp_lookup_entry)(drm_device_t *dev, +static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t *dev, unsigned long handle) { drm_agp_mem_t *entry; @@ -360,7 +360,7 @@ static drm_agp_mem_t *DRM(agp_lookup_entry)(drm_device_t *dev, * Verifies the AGP device is present and acquired, looks-up the AGP memory * entry and passes it to the agp_unbind() function. */ -int DRM(agp_unbind_ioctl)(struct inode *inode, struct file *filp, +int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; @@ -372,10 +372,10 @@ int DRM(agp_unbind_ioctl)(struct inode *inode, struct file *filp, if (!dev->agp || !dev->agp->acquired) return -EINVAL; if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request))) return -EFAULT; - if (!(entry = DRM(agp_lookup_entry)(dev, request.handle))) + if (!(entry = drm_agp_lookup_entry(dev, request.handle))) return -EINVAL; if (!entry->bound) return -EINVAL; - ret = DRM(agp_unbind)(entry->memory); + ret = drm_agp_unbind(entry->memory); if (ret == 0) entry->bound = 0; return ret; @@ -394,7 +394,7 @@ int DRM(agp_unbind_ioctl)(struct inode *inode, struct file *filp, * is currently bound into the GATT. Looks-up the AGP memory entry and passes * it to agp_bind() function. */ -int DRM(agp_bind_ioctl)(struct inode *inode, struct file *filp, +int drm_agp_bind_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; @@ -408,11 +408,11 @@ int DRM(agp_bind_ioctl)(struct inode *inode, struct file *filp, return -EINVAL; if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request))) return -EFAULT; - if (!(entry = DRM(agp_lookup_entry)(dev, request.handle))) + if (!(entry = drm_agp_lookup_entry(dev, request.handle))) return -EINVAL; if (entry->bound) return -EINVAL; page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE; - if ((retcode = DRM(agp_bind)(entry->memory, page))) return retcode; + if ((retcode = drm_agp_bind(entry->memory, page))) return retcode; entry->bound = dev->agp->base + (page << PAGE_SHIFT); DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n", dev->agp->base, entry->bound); @@ -433,7 +433,7 @@ int DRM(agp_bind_ioctl)(struct inode *inode, struct file *filp, * agp_unbind(). Frees it via agp_free() as well as the entry itself * and unlinks from the doubly linked list it's inserted in. */ -int DRM(agp_free_ioctl)(struct inode *inode, struct file *filp, +int drm_agp_free_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; @@ -444,15 +444,15 @@ int DRM(agp_free_ioctl)(struct inode *inode, struct file *filp, if (!dev->agp || !dev->agp->acquired) return -EINVAL; if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request))) return -EFAULT; - if (!(entry = DRM(agp_lookup_entry)(dev, request.handle))) + if (!(entry = drm_agp_lookup_entry(dev, request.handle))) return -EINVAL; - if (entry->bound) DRM(agp_unbind)(entry->memory); + if (entry->bound) drm_agp_unbind(entry->memory); if (entry->prev) entry->prev->next = entry->next; else dev->agp->memory = entry->next; if (entry->next) entry->next->prev = entry->prev; - DRM(agp_free)(entry->memory); - DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS); + drm_agp_free(entry->memory); + drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); return 0; } @@ -468,7 +468,7 @@ int DRM(agp_free_ioctl)(struct inode *inode, struct file *filp, * * Creates and initializes a drm_agp_head structure in drm_device_t::agp. */ -void DRM(agp_init)(drm_device_t *dev) +void drm_agp_init(drm_device_t *dev) { drm_agp_head_t *head = NULL; @@ -480,13 +480,13 @@ void DRM(agp_init)(drm_device_t *dev) } ++drm_agp_refcount; - if (!(head = DRM(alloc)(sizeof(*head), DRM_MEM_AGPLISTS))) + if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS))) return; memset((void *)head, 0, sizeof(*head)); drm_agp->copy_info(&head->agp_info); if (head->agp_info.chipset == NOT_SUPPORTED) { - DRM(free)(head, sizeof(*head), DRM_MEM_AGPLISTS); + drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS); return; } head->memory = NULL; @@ -510,7 +510,7 @@ void DRM(agp_init)(drm_device_t *dev) /** * Free the device AGP resources. */ -void DRM(agp_cleanup)(drm_device_t *dev) +void drm_agp_cleanup(drm_device_t *dev) { if ( dev->agp ) { drm_agp_mem_t *entry; @@ -521,19 +521,19 @@ void DRM(agp_cleanup)(drm_device_t *dev) for ( entry = dev->agp->memory ; entry ; entry = nexte ) { nexte = entry->next; if ( entry->bound ) - DRM(agp_unbind)( entry->memory ); - DRM(agp_free)( entry->memory ); - DRM(free)( entry, sizeof(*entry), DRM_MEM_AGPLISTS ); + drm_agp_unbind( entry->memory ); + drm_agp_free( entry->memory ); + drm_free( entry, sizeof(*entry), DRM_MEM_AGPLISTS ); } dev->agp->memory = NULL; if ( dev->agp->acquired ) - DRM(agp_release)(); + drm_agp_release(); dev->agp->acquired = 0; dev->agp->enabled = 0; - DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS ); + drm_free( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS ); dev->agp = NULL; } diff --git a/linux/drm_agp.h b/linux/drm_agp.h index 2cf1b547b..727441569 100644 --- a/linux/drm_agp.h +++ b/linux/drm_agp.h @@ -63,7 +63,7 @@ typedef struct drm_agp_mem { /** * AGP data. * - * \sa DRM(agp_init)() and drm_device::agp. + * \sa drm_agp_init() and drm_device::agp. */ typedef struct drm_agp_head { agp_kern_info agp_info; /**< AGP device information */ @@ -81,25 +81,25 @@ typedef struct drm_agp_head { /** \name Prototypes */ /*@{*/ -extern int DRM(agp_acquire)(void); -extern void DRM(agp_release)(void); -extern void DRM(agp_enable)(unsigned long mode); -extern agp_memory *DRM(agp_alloc)(size_t pages, u32 type); -extern int DRM(agp_free)(agp_memory *handle); -extern int DRM(agp_bind)(agp_memory *handle, off_t start); -extern int DRM(agp_unbind)(agp_memory *handle); - -extern int DRM(agp_acquire_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern int DRM(agp_release_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern int DRM(agp_enable_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern int DRM(agp_info_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern int DRM(agp_alloc_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern int DRM(agp_free_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern int DRM(agp_bind_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern int DRM(agp_unbind_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); - -extern void DRM(agp_init)(drm_device_t *dev); -extern void DRM(agp_cleanup)(drm_device_t *dev); +extern int drm_agp_acquire(void); +extern void drm_agp_release(void); +extern void drm_agp_enable(unsigned long mode); +extern agp_memory *drm_agp_alloc(size_t pages, u32 type); +extern int drm_agp_free(agp_memory *handle); +extern int drm_agp_bind(agp_memory *handle, off_t start); +extern int drm_agp_unbind(agp_memory *handle); + +extern int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern int drm_agp_release_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern int drm_agp_enable_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern int drm_agp_info_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern int drm_agp_free_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern int drm_agp_bind_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); + +extern void drm_agp_init(drm_device_t *dev); +extern void drm_agp_cleanup(drm_device_t *dev); /*@}*/ diff --git a/linux/drm_bufs_tmp.h b/linux/drm_bufs.c index 3e5396e0f..0c8e121dd 100644 --- a/linux/drm_bufs_tmp.h +++ b/linux/drm_bufs.c @@ -1,5 +1,5 @@ /** - * \file drm_bufs.h + * \file drm_bufs_tmp.h * Buffer management template. * * \author Rickard E. (Rik) Faith <faith@valinux.com> @@ -62,9 +62,8 @@ int drm_pool_create(drm_pool_t *pool, size_t count, size_t size) pool->count = count pool->size = size; - pool->buffers = (drm_pool_buffer_t *)DRM(alloc)( - count*sizeof(drm_buffer_t), - DRM_MEM_BUFLISTS); + pool->buffers = (drm_pool_buffer_t *)drm_alloc( + count*sizeof(drm_buffer_t)); if (!pool->buffers) return -ENOMEM; @@ -80,7 +79,7 @@ int drm_pool_create(drm_pool_t *pool, size_t count, size_t size) */ void drm_pool_destroy(drm_pool_t *pool) { - DRM(free)(pool->buffers, pool->count*sizeof(drm_buffer_t), DRM_MEM_BUFLISTS); + drm_free(pool->buffers, pool->count*sizeof(drm_buffer_t)); } /** @@ -101,6 +100,192 @@ void drm_pool_free(drm_device_t *dev, drm_pool_t *pool) /*@}*/ +/** \name Buffer pool allocation */ +/*@{*/ + +/** + * PCI consistent memory pool. + * + * This structure inherits from drm_pool and is used by drm_pool_pci_alloc() + * and drm_pool_pci_free() to store PCI specific data of the pool. + */ +typedef struct drm_pool_pci { + drm_pool_t base; /**< base pool */ + void *handle; /**< opaque handle to the PCI memory pool */ +} drm_pool_pci_t; + +/** + * Free a pool of PCI consistent memory. + * + * This is called internally by drm_pool_free(). + */ +static void drm_pool_pci_free(drm_device_t *dev, drm_pool_t *base) +{ + drm_pool_pci_t *pool = (drm_pool_pci_t *)base; + drm_pool_buffer_t *buffer; + unsigned i; + + for (i = 0; i < ; ++i) { + buffer = &pool->base.buffers[i]; + drm_pci_pool_free(pool->handle, buffer->cpuaddr, buffer->busaddr); + } + + drm_pci_pool_destroy(dev, pool->handle); + + drm_pool_destroy(pool); + + drm_free(pool); +} + +/** + * Allocate a pool of PCI consistent memory. + * + * Once no longer needed, the pool should be freed calling drm_pool_free(). + * + * Internally this function creates (and later returns) a drm_pool_pci + * structure, allocating the PCI memory by successive calls to + * drm_pci_pool_alloc(). + */ +drm_pool_t *drm_pool_pci_alloc(drm_device_t *dev, size_t count, size_t size, size_t align) +{ + drm_pool_pci_t *pool; + drm_pool_buffer_t *buffer; + unsigned i, j; + + if (!(pool = (drm_pool_pci_t *)drm_alloc( sizeof(drm_pool_pci_t)))) + goto failed_alloc; + + if (drm_pool_create(&pool->base, count, size)) + goto failed_pool_create; + + if (!(pool->handle = drm_pci_pool_create( dev, size, align ))) + goto failed_pci_pool_create; + + for (i = 0; i < count; ++i) { + buffer = &pool->base.buffers[i]; + if (!(buffer->cpuaddr = drm_pci_pool_alloc(pool->handle, &buffer->busaddr))) + goto failed_pci_pool_alloc; + } + + pool->base->free = drm_pool_pci_free; + + /* Success */ + return &pool->base; + + /* Failure */ +failed_pci_pool_alloc: + for (j = 0; j < i; ++j) { + buffer = &pool->base.buffers[j]; + drm_pci_pool_free(pool->handle, buffer->cpuaddr, buffer->busaddr); + } + + drm_pci_pool_destroy(dev, pool->handle); + +failed_pci_pool_create: + drm_pool_destroy(pool); + +failed_pool_create: + drm_free(pool); + +failed_alloc: + return NULL; +} + +/** + * Free a pool of AGP memory. + * + * This is called internally by drm_pool_free(). + */ +static void drm_pool_agp_free(drm_device_t *dev, drm_pool_t *pool) +{ + drm_pool_destroy(pool); + + drm_free(pool); +} + +/** + * Allocate a pool of AGP memory. + * + * Once no longer needed, the pool should be freed calling drm_pool_free(). + */ +drm_pool_t *drm_pool_agp_alloc(drm_device_t *dev, unsigned offset, size_t count, size_t size, size_t align) +{ + drm_pool_t *pool; + drm_pool_buffer_t *buffer; + unsigned i, j; + + if (!dev->agp) + return NULL; + + if (!(pool = (drm_pool_t *)drm_alloc( sizeof(drm_pool_t)))) + return NULL; + + if (drm_pool_create(pool, count, size)) { + drm_free(pool); + return NULL; + } + + for (i = 0; i < count; ++i) { + buffer = pool->buffers[i]; + buffer->cpuaddr = (void *)(dev->agp->base + offset); + buffer->busaddr = dev->agp->base + offset; + offset += align; + } + + pool->free = drm_pool_agp_free; + + return pool; +} + +/** + * Free a pool of scatter/gather memory. + * + * This is called internally by drm_pool_free(). + */ +static void drm_pool_sg_free(drm_device_t *dev, drm_pool_t *pool) +{ + drm_pool_destroy(pool); + + drm_free(pool); +} + +/** + * Allocate a pool of AGP memory. + * + * Once no longer needed, the pool should be freed calling drm_pool_free(). + */ +drm_pool_t *drm_pool_sg_alloc(drm_device_t *dev, unsigned offset, size_t count, size_t size, size_t align) +{ + drm_pool_t *pool; + drm_pool_buffer_t *buffer; + unsigned i, j; + + if (!dev->sg) + return NULL; + + if (!(pool = (drm_pool_t *)drm_alloc( sizeof(drm_pool_t)))) + return NULL; + + if (drm_pool_create(pool, count, size)) { + drm_free(pool); + return NULL; + } + + for (i = 0; i < count; ++i) { + buffer = pool->buffers[i]; + buffer->cpuaddr = (void *)(dev->sg->handle + offset); + buffer->busaddr = offset; + offset += align; + } + + pool->free = drm_pool_sg_free; + + return pool; +} + +/*@}*/ + + /** \name Free-list management */ /*@{*/ @@ -134,7 +319,7 @@ int drm_freelist2_create(drm_freelist2_t *freelist, drm_pool_t *pool, size_t str freelist->pool = pool; freelist->stride = stride; - freelist->entries = DRM(alloc)( + freelist->entries = drm_alloc( pool->count*stride, DRM_MEM_BUFLISTS); @@ -158,7 +343,7 @@ int drm_freelist2_create(drm_freelist2_t *freelist, drm_pool_t *pool, size_t str */ void drm_freelist2_destroy(drm_freelist2_t *freelist) { - DRM(free)(freelist->entries, freelist->pool->count*freelist->stride, DRM_MEM_BUFLISTS); + drm_free(freelist->entries, freelist->pool->count*freelist->stride, DRM_MEM_BUFLISTS); } /** @@ -223,7 +408,6 @@ int drm_freelist2_update(drm_freelist2_t *freelist, int bail_out) return count; } - /** * Get a free buffer from the free-list. @@ -288,28 +472,8 @@ int drm_freelist2_wait_helper( -/****************************************************************************/ -/* Deprecated stuff */ - -#ifndef __HAVE_PCI_DMA -#define __HAVE_PCI_DMA 0 -#endif - -#ifndef __HAVE_SG -#define __HAVE_SG 0 -#endif - -#ifndef DRIVER_BUF_PRIV_T -#define DRIVER_BUF_PRIV_T u32 -#endif -#ifndef DRIVER_AGP_BUFFERS_MAP -#if __HAVE_AGP && __HAVE_DMA -#error "You must define DRIVER_AGP_BUFFERS_MAP()" -#else -#define DRIVER_AGP_BUFFERS_MAP( dev ) NULL -#endif -#endif - +/** \name Backwards compatability ioctl's */ +/*@{*/ /** * Compute size order. Returns the exponent of the smaller power of two which @@ -334,274 +498,156 @@ int DRM(order)( unsigned long size ) } /** - * Ioctl to specify a range of memory that is available for mapping by a non-root process. - * - * \param inode device inode. - * \param filp file pointer. - * \param cmd command. - * \param arg pointer to a drm_map structure. - * \return zero on success or a negative value on error. + * Add and allocate buffers in PCI memory. * - * Adjusts the memory offset to its absolute value according to the mapping - * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where - * applicable and if supported by the kernel. + * \note This ioctl is (and always has been) the \e only way to allocate PCI + * buffers from user space. */ -int DRM(addmap_ioctl)( struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg ) +int DRM(addbufs_pci_ioctl)( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) { - drm_file_t *priv = filp->private_data; + drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - drm_map_t *map; - drm_map_list_t *list; - - if ( !(filp->f_mode & 3) ) return -EACCES; /* Require read/write */ + drm_device_dma_t *dma = dev->dma; + drm_buf_desc_t request; + int count; + int order; + int size; + int total; + int page_order; + drm_buf_entry_t *entry; + unsigned long page; + drm_buf_t *buf; + int alignment; + unsigned long offset; + int i; + int byte_count; + int page_count; + unsigned long *temp_pagelist; + drm_buf_t **temp_buflist; - map = DRM(alloc)( sizeof(*map), DRM_MEM_MAPS ); - if ( !map ) - return -ENOMEM; + if ( !dma ) return -EINVAL; - if ( copy_from_user( map, (drm_map_t *)arg, sizeof(*map) ) ) { - DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); + if ( copy_from_user( &request, (drm_buf_desc_t *)arg, + sizeof(request) ) ) return -EFAULT; - } - /* Only allow shared memory to be removable since we only keep enough - * book keeping information about shared memory to allow for removal - * when processes fork. - */ - if ( (map->flags & _DRM_REMOVABLE) && map->type != _DRM_SHM ) { - DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); - return -EINVAL; - } - DRM_DEBUG( "offset = 0x%08lx, size = 0x%08lx, type = %d\n", - map->offset, map->size, map->type ); - if ( (map->offset & (~PAGE_MASK)) || (map->size & (~PAGE_MASK)) ) { - DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); - return -EINVAL; - } - map->mtrr = -1; - map->handle = 0; + count = request.count; + order = DRM(order)( request.size ); + size = 1 << order; - switch ( map->type ) { - case _DRM_REGISTERS: - case _DRM_FRAME_BUFFER: -#if !defined(__sparc__) && !defined(__alpha__) - if ( map->offset + map->size < map->offset || - map->offset < virt_to_phys(high_memory) ) { - DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); - return -EINVAL; - } -#endif -#ifdef __alpha__ - map->offset += dev->hose->mem_space->start; -#endif -#if __REALLY_HAVE_MTRR - if ( map->type == _DRM_FRAME_BUFFER || - (map->flags & _DRM_WRITE_COMBINING) ) { - map->mtrr = mtrr_add( map->offset, map->size, - MTRR_TYPE_WRCOMB, 1 ); - } -#endif - map->handle = DRM(ioremap)( map->offset, map->size, dev ); - break; + DRM_DEBUG( "count=%d, size=%d (%d), order=%d, queue_count=%d\n", + request.count, request.size, size, + order, dev->queue_count ); - case _DRM_SHM: - map->handle = vmalloc_32(map->size); - DRM_DEBUG( "%lu %d %p\n", - map->size, DRM(order)( map->size ), map->handle ); - if ( !map->handle ) { - DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); - return -ENOMEM; - } - map->offset = (unsigned long)map->handle; - if ( map->flags & _DRM_CONTAINS_LOCK ) { - dev->sigdata.lock = - dev->lock.hw_lock = map->handle; /* Pointer to lock */ - } - break; -#if __REALLY_HAVE_AGP - case _DRM_AGP: -#ifdef __alpha__ - map->offset += dev->hose->mem_space->start; -#endif - map->offset += dev->agp->base; - map->mtrr = dev->agp->agp_mtrr; /* for getmap */ - break; -#endif - -#if __HAVE_SG - case _DRM_SCATTER_GATHER: - if (!dev->sg) { - DRM(free)(map, sizeof(*map), DRM_MEM_MAPS); - return -EINVAL; - } - map->offset += dev->sg->handle; - break; -#endif + if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL; + if ( dev->queue_count ) return -EBUSY; /* Not while in use */ - default: - DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); - return -EINVAL; - } + 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; - list = DRM(alloc)(sizeof(*list), DRM_MEM_MAPS); - if(!list) { - DRM(free)(map, sizeof(*map), DRM_MEM_MAPS); - return -EINVAL; + spin_lock( &dev->count_lock ); + if ( dev->buf_use ) { + spin_unlock( &dev->count_lock ); + return -EBUSY; } - memset(list, 0, sizeof(*list)); - list->map = map; - - down(&dev->struct_sem); - list_add(&list->head, &dev->maplist->head); - up(&dev->struct_sem); + atomic_inc( &dev->buf_alloc ); + spin_unlock( &dev->count_lock ); - if ( copy_to_user( (drm_map_t *)arg, map, sizeof(*map) ) ) - return -EFAULT; - if ( map->type != _DRM_SHM ) { - if ( copy_to_user( &((drm_map_t *)arg)->handle, - &map->offset, - sizeof(map->offset) ) ) - return -EFAULT; + down( &dev->struct_sem ); + entry = &dma->bufs[order]; + if ( entry->pool ) { + up( &dev->struct_sem ); + atomic_dec( &dev->buf_alloc ); + return -ENOMEM; /* May only call once for each order */ } - return 0; -} - - -/** - * Remove a map private from list and deallocate resources if the mapping - * isn't in use. - * - * \param inode device inode. - * \param filp file pointer. - * \param cmd command. - * \param arg pointer to a drm_map_t structure. - * \return zero on success or a negative value on error. - * - * Searches the map on drm_device::maplist, removes it from the list, see if - * its being used, and free any associate resource (such as MTRR's) if it's not - * being on use. - * - * \sa addmap(). - */ -int DRM(rmmap_ioctl)(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; - struct list_head *list; - drm_map_list_t *r_list = NULL; - drm_vma_entry_t *pt, *prev; - drm_map_t *map; - drm_map_t request; - int found_maps = 0; - if (copy_from_user(&request, (drm_map_t *)arg, - sizeof(request))) { - return -EFAULT; + if (count < 0 || count > 4096) { + up( &dev->struct_sem ); + atomic_dec( &dev->buf_alloc ); + return -EINVAL; } - down(&dev->struct_sem); - list = &dev->maplist->head; - list_for_each(list, &dev->maplist->head) { - r_list = list_entry(list, drm_map_list_t, head); + entry->pool = drm_pool_pci_alloc(dev, count, size, alignment); + if ( !entry->pool ) { + up( &dev->struct_sem ); + atomic_dec( &dev->buf_alloc ); + return -ENOMEM; + } - if(r_list->map && - r_list->map->handle == request.handle && - r_list->map->flags & _DRM_REMOVABLE) break; + entry->seglist = drm_alloc( count * sizeof(*entry->seglist), + DRM_MEM_SEGS ); + if ( !entry->seglist ) { + drm_free( entry->buflist ); + up( &dev->struct_sem ); + atomic_dec( &dev->buf_alloc ); + return -ENOMEM; } + memset( entry->seglist, 0, count * sizeof(*entry->seglist) ); - /* List has wrapped around to the head pointer, or its empty we didn't - * find anything. + /* Keep the original pagelist until we know all the allocations + * have succeeded */ - if(list == (&dev->maplist->head)) { - up(&dev->struct_sem); - return -EINVAL; + temp_pagelist = drm_alloc( (dma->page_count + (count << page_order)) + * sizeof(*dma->pagelist) ); + if (!temp_pagelist) { + drm_pool_free( entry->pool ); + drm_free( entry->seglist ); + up( &dev->struct_sem ); + atomic_dec( &dev->buf_alloc ); + return -ENOMEM; } - map = r_list->map; - list_del(list); - DRM(free)(list, sizeof(*list), DRM_MEM_MAPS); + memcpy(temp_pagelist, + dma->pagelist, + dma->page_count * sizeof(*dma->pagelist)); + DRM_DEBUG( "pagelist: %d entries\n", + dma->page_count + (count << page_order) ); - for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) { - if (pt->vma->vm_private_data == map) found_maps++; - } + entry->buf_size = size; + entry->page_order = page_order; + byte_count = 0; + page_count = 0; - if(!found_maps) { - switch (map->type) { - case _DRM_REGISTERS: - case _DRM_FRAME_BUFFER: -#if __REALLY_HAVE_MTRR - if (map->mtrr >= 0) { - int retcode; - retcode = mtrr_del(map->mtrr, - map->offset, - map->size); - DRM_DEBUG("mtrr_del = %d\n", retcode); - } -#endif - DRM(ioremapfree)(map->handle, map->size, dev); - break; - case _DRM_SHM: - vfree(map->handle); - break; - case _DRM_AGP: - case _DRM_SCATTER_GATHER: - break; + while ( entry->buf_count < count ) { + /* FIXME: What to put in here? */ + page = DRM(alloc_pages)( page_order, DRM_MEM_DMA ); + entry->seglist[entry->seg_count++] = page; + for ( i = 0 ; i < (1 << page_order) ; i++ ) { + DRM_DEBUG( "page %d @ 0x%08lx\n", + dma->page_count + page_count, + page + PAGE_SIZE * i ); + temp_pagelist[dma->page_count + page_count++] + = page + PAGE_SIZE * i; } - DRM(free)(map, sizeof(*map), DRM_MEM_MAPS); + byte_count += PAGE_SIZE << page_order; } - up(&dev->struct_sem); - return 0; -} -#if __HAVE_DMA + /* No allocations failed, so now we can replace the orginal pagelist + * with the new one. + */ + if (dma->page_count) { + drm_free(dma->pagelist); + } + dma->pagelist = temp_pagelist; -/** - * Cleanup after an error on one of the addbufs() functions. - * - * \param entry buffer entry where the error occurred. - * - * Frees any pages and buffers associated with the given entry. - */ -static void DRM(cleanup_buf_error)(drm_buf_entry_t *entry) -{ - int i; + dma->buf_count += entry->buf_count; + dma->seg_count += entry->seg_count; + dma->page_count += entry->seg_count << page_order; + dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order); - if (entry->seg_count) { - for (i = 0; i < entry->seg_count; i++) { - if (entry->seglist[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); + up( &dev->struct_sem ); - entry->seg_count = 0; - } + request.count = entry->buf_count; + request.size = size; - 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 ( copy_to_user( (drm_buf_desc_t *)arg, &request, sizeof(request) ) ) + return -EFAULT; -#if __HAVE_DMA_FREELIST - DRM(freelist_destroy)(&entry->freelist); -#endif + atomic_dec( &dev->buf_alloc ); + return 0; - entry->buf_count = 0; - } } #if __REALLY_HAVE_AGP @@ -690,72 +736,12 @@ int DRM(addbufs_agp_ioctl)( struct inode *inode, struct file *filp, return -EINVAL; } - entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist), - DRM_MEM_BUFS ); - if ( !entry->buflist ) { + entry->pool = drm_pool_pci_alloc(dev, request.agp_start, count, size, alignment); + if ( !entry->pool ) { 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); - buf->next = NULL; - buf->waiting = 0; - buf->pending = 0; - init_waitqueue_head( &buf->dma_wait ); - buf->filp = 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; - } - memset( buf->dev_private, 0, buf->dev_priv_size ); - - 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; for ( i = 0 ; i < entry->buf_count ; i++ ) { dma->buflist[i + dma->buf_count] = &entry->buflist[i]; @@ -767,12 +753,6 @@ int DRM(addbufs_agp_ioctl)( struct inode *inode, struct file *filp, 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] ); - } -#endif up( &dev->struct_sem ); request.count = entry->buf_count; @@ -788,251 +768,6 @@ int DRM(addbufs_agp_ioctl)( struct inode *inode, struct file *filp, } #endif /* __REALLY_HAVE_AGP */ -#if __HAVE_PCI_DMA -/** - * Add and allocate buffers in PCI memory. - * - * \note This ioctl is currently the \e only way to allocate PCI buffers. - * - * \todo It should be modified to use the Linux PCI buffer API. - */ -int DRM(addbufs_pci_ioctl)( 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; - int count; - int order; - int size; - int total; - int page_order; - drm_buf_entry_t *entry; - unsigned long page; - drm_buf_t *buf; - int alignment; - unsigned long offset; - int i; - int byte_count; - int page_count; - unsigned long *temp_pagelist; - 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; - - DRM_DEBUG( "count=%d, size=%d (%d), order=%d, queue_count=%d\n", - request.count, request.size, size, - order, dev->queue_count ); - - if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL; - if ( dev->queue_count ) return -EBUSY; /* Not while in use */ - - 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; - - 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 ); - atomic_dec( &dev->buf_alloc ); - 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->seglist = DRM(alloc)( count * sizeof(*entry->seglist), - DRM_MEM_SEGS ); - if ( !entry->seglist ) { - DRM(free)( entry->buflist, - count * sizeof(*entry->buflist), - DRM_MEM_BUFS ); - up( &dev->struct_sem ); - atomic_dec( &dev->buf_alloc ); - return -ENOMEM; - } - memset( entry->seglist, 0, count * sizeof(*entry->seglist) ); - - /* Keep the original pagelist until we know all the allocations - * have succeeded - */ - temp_pagelist = DRM(alloc)( (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; - } - memcpy(temp_pagelist, - dma->pagelist, - dma->page_count * sizeof(*dma->pagelist)); - DRM_DEBUG( "pagelist: %d entries\n", - dma->page_count + (count << page_order) ); - - entry->buf_size = size; - entry->page_order = page_order; - byte_count = 0; - page_count = 0; - - while ( entry->buf_count < count ) { - page = DRM(alloc_pages)( page_order, DRM_MEM_DMA ); - if ( !page ) { - /* Set count correctly so we free the proper amount. */ - entry->buf_count = count; - entry->seg_count = count; - DRM(cleanup_buf_error)(entry); - DRM(free)( temp_pagelist, - (dma->page_count + (count << page_order)) - * sizeof(*dma->pagelist), - DRM_MEM_PAGES ); - up( &dev->struct_sem ); - atomic_dec( &dev->buf_alloc ); - return -ENOMEM; - } - entry->seglist[entry->seg_count++] = page; - for ( i = 0 ; i < (1 << page_order) ; i++ ) { - DRM_DEBUG( "page %d @ 0x%08lx\n", - dma->page_count + page_count, - page + PAGE_SIZE * i ); - temp_pagelist[dma->page_count + page_count++] - = page + PAGE_SIZE * i; - } - for ( offset = 0 ; - offset + size <= total && 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 + byte_count + offset); - buf->address = (void *)(page + offset); - buf->next = NULL; - buf->waiting = 0; - buf->pending = 0; - init_waitqueue_head( &buf->dma_wait ); - buf->filp = 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; - entry->seg_count = count; - DRM(cleanup_buf_error)(entry); - DRM(free)( temp_pagelist, - (dma->page_count + (count << page_order)) - * sizeof(*dma->pagelist), - DRM_MEM_PAGES ); - up( &dev->struct_sem ); - atomic_dec( &dev->buf_alloc ); - return -ENOMEM; - } - memset( buf->dev_private, 0, buf->dev_priv_size ); - - DRM_DEBUG( "buffer %d @ %p\n", - entry->buf_count, buf->address ); - } - byte_count += PAGE_SIZE << page_order; - } - - 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); - DRM(free)( temp_pagelist, - (dma->page_count + (count << page_order)) - * sizeof(*dma->pagelist), - DRM_MEM_PAGES ); - 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]; - } - - /* No allocations failed, so now we can replace the orginal pagelist - * with the new one. - */ - if (dma->page_count) { - DRM(free)(dma->pagelist, - dma->page_count * sizeof(*dma->pagelist), - DRM_MEM_PAGES); - } - dma->pagelist = temp_pagelist; - - dma->buf_count += entry->buf_count; - dma->seg_count += entry->seg_count; - dma->page_count += entry->seg_count << page_order; - dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order); - -#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] ); - } -#endif - 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; - - atomic_dec( &dev->buf_alloc ); - return 0; - -} -#endif /* __HAVE_PCI_DMA */ - -#if __HAVE_SG /** * Add scatter/gather buffers. */ @@ -1108,74 +843,16 @@ int DRM(addbufs_sg_ioctl)( struct inode *inode, struct file *filp, return -EINVAL; } - entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist), - DRM_MEM_BUFS ); - if ( !entry->buflist ) { + entry->pool = drm_pool_sg_alloc(dev, request.agp_start, count, size, alignment); + if ( !entry->pool ) { 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->filp = 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; - } - - memset( buf->dev_private, 0, buf->dev_priv_size ); - - 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; - for ( i = 0 ; i < entry->buf_count ; i++ ) { dma->buflist[i + dma->buf_count] = &entry->buflist[i]; } @@ -1186,12 +863,6 @@ int DRM(addbufs_sg_ioctl)( struct inode *inode, struct file *filp, 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] ); - } -#endif up( &dev->struct_sem ); request.count = entry->buf_count; @@ -1205,7 +876,6 @@ int DRM(addbufs_sg_ioctl)( struct inode *inode, struct file *filp, atomic_dec( &dev->buf_alloc ); return 0; } -#endif /* __HAVE_SG */ /** * Add buffers for DMA transfers. @@ -1561,4 +1231,233 @@ int DRM(mapbufs_ioctl)( struct inode *inode, struct file *filp, return retcode; } +/** + * Ioctl to specify a range of memory that is available for mapping by a non-root process. + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg pointer to a drm_map structure. + * \return zero on success or a negative value on error. + * + * Adjusts the memory offset to its absolute value according to the mapping + * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where + * applicable and if supported by the kernel. + */ +int DRM(addmap_ioctl)( 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_map_t *map; + drm_map_list_t *list; + + if ( !(filp->f_mode & 3) ) return -EACCES; /* Require read/write */ + + map = drm_alloc( sizeof(*map), DRM_MEM_MAPS ); + if ( !map ) + return -ENOMEM; + + if ( copy_from_user( map, (drm_map_t *)arg, sizeof(*map) ) ) { + drm_free( map, sizeof(*map), DRM_MEM_MAPS ); + return -EFAULT; + } + + /* Only allow shared memory to be removable since we only keep enough + * book keeping information about shared memory to allow for removal + * when processes fork. + */ + if ( (map->flags & _DRM_REMOVABLE) && map->type != _DRM_SHM ) { + drm_free( map, sizeof(*map), DRM_MEM_MAPS ); + return -EINVAL; + } + DRM_DEBUG( "offset = 0x%08lx, size = 0x%08lx, type = %d\n", + map->offset, map->size, map->type ); + if ( (map->offset & (~PAGE_MASK)) || (map->size & (~PAGE_MASK)) ) { + drm_free( map, sizeof(*map), DRM_MEM_MAPS ); + return -EINVAL; + } + map->mtrr = -1; + map->handle = 0; + + switch ( map->type ) { + case _DRM_REGISTERS: + case _DRM_FRAME_BUFFER: +#if !defined(__sparc__) && !defined(__alpha__) + if ( map->offset + map->size < map->offset || + map->offset < virt_to_phys(high_memory) ) { + drm_free( map, sizeof(*map), DRM_MEM_MAPS ); + return -EINVAL; + } +#endif +#ifdef __alpha__ + map->offset += dev->hose->mem_space->start; +#endif +#if __REALLY_HAVE_MTRR + if ( map->type == _DRM_FRAME_BUFFER || + (map->flags & _DRM_WRITE_COMBINING) ) { + map->mtrr = mtrr_add( map->offset, map->size, + MTRR_TYPE_WRCOMB, 1 ); + } +#endif + map->handle = DRM(ioremap)( map->offset, map->size, dev ); + break; + + case _DRM_SHM: + map->handle = vmalloc_32(map->size); + DRM_DEBUG( "%lu %d %p\n", + map->size, DRM(order)( map->size ), map->handle ); + if ( !map->handle ) { + drm_free( map, sizeof(*map), DRM_MEM_MAPS ); + return -ENOMEM; + } + map->offset = (unsigned long)map->handle; + if ( map->flags & _DRM_CONTAINS_LOCK ) { + dev->sigdata.lock = + dev->lock.hw_lock = map->handle; /* Pointer to lock */ + } + break; +#if __REALLY_HAVE_AGP + case _DRM_AGP: +#ifdef __alpha__ + map->offset += dev->hose->mem_space->start; +#endif + map->offset += dev->agp->base; + map->mtrr = dev->agp->agp_mtrr; /* for getmap */ + break; +#endif + +#if __HAVE_SG + case _DRM_SCATTER_GATHER: + if (!dev->sg) { + drm_free(map, sizeof(*map), DRM_MEM_MAPS); + return -EINVAL; + } + map->offset += dev->sg->handle; + break; +#endif + + default: + drm_free( map, sizeof(*map), DRM_MEM_MAPS ); + return -EINVAL; + } + + list = drm_alloc(sizeof(*list), DRM_MEM_MAPS); + if(!list) { + drm_free(map, sizeof(*map), DRM_MEM_MAPS); + return -EINVAL; + } + memset(list, 0, sizeof(*list)); + list->map = map; + + down(&dev->struct_sem); + list_add(&list->head, &dev->maplist->head); + up(&dev->struct_sem); + + if ( copy_to_user( (drm_map_t *)arg, map, sizeof(*map) ) ) + return -EFAULT; + if ( map->type != _DRM_SHM ) { + if ( copy_to_user( &((drm_map_t *)arg)->handle, + &map->offset, + sizeof(map->offset) ) ) + return -EFAULT; + } + return 0; +} + + +/** + * Remove a map private from list and deallocate resources if the mapping + * isn't in use. + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg pointer to a drm_map_t structure. + * \return zero on success or a negative value on error. + * + * Searches the map on drm_device::maplist, removes it from the list, see if + * its being used, and free any associate resource (such as MTRR's) if it's not + * being on use. + * + * \sa addmap(). + */ +int DRM(rmmap_ioctl)(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; + struct list_head *list; + drm_map_list_t *r_list = NULL; + drm_vma_entry_t *pt, *prev; + drm_map_t *map; + drm_map_t request; + int found_maps = 0; + + if (copy_from_user(&request, (drm_map_t *)arg, + sizeof(request))) { + return -EFAULT; + } + + down(&dev->struct_sem); + list = &dev->maplist->head; + list_for_each(list, &dev->maplist->head) { + r_list = list_entry(list, drm_map_list_t, head); + + if(r_list->map && + r_list->map->handle == request.handle && + r_list->map->flags & _DRM_REMOVABLE) break; + } + + /* List has wrapped around to the head pointer, or its empty we didn't + * find anything. + */ + if(list == (&dev->maplist->head)) { + up(&dev->struct_sem); + return -EINVAL; + } + map = r_list->map; + list_del(list); + drm_free(list, sizeof(*list), DRM_MEM_MAPS); + + for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) { + if (pt->vma->vm_private_data == map) found_maps++; + } + + if(!found_maps) { + switch (map->type) { + case _DRM_REGISTERS: + case _DRM_FRAME_BUFFER: +#if __REALLY_HAVE_MTRR + if (map->mtrr >= 0) { + int retcode; + retcode = mtrr_del(map->mtrr, + map->offset, + map->size); + DRM_DEBUG("mtrr_del = %d\n", retcode); + } +#endif + DRM(ioremapfree)(map->handle, map->size, dev); + break; + case _DRM_SHM: + vfree(map->handle); + break; + case _DRM_AGP: + case _DRM_SCATTER_GATHER: + break; + } + drm_free(map, sizeof(*map), DRM_MEM_MAPS); + } + up(&dev->struct_sem); + return 0; +} + + #endif /* __HAVE_DMA */ +/*@}*/ + + +/** \name Device initialization and cleanup */ +/*@{*/ + +/*@}*/ diff --git a/linux/drm_bufs.h b/linux/drm_bufs.h index 58b7e0e1d..c35c01312 100644 --- a/linux/drm_bufs.h +++ b/linux/drm_bufs.h @@ -1,23 +1,10 @@ /** * \file drm_bufs.h - * Buffer management. + * DMA buffers management. * * \author Rickard E. (Rik) Faith <faith@valinux.com> * \author Gareth Hughes <gareth@valinux.com> * \author José Fonseca <jrfonseca@tungstengraphics.com> - * - * \todo The current buffer management system assumes too much and is severily - * limited: - * - It expects to all buffers to be used by clients, and has little provisions - * for private buffers (such as ring buffers, primary DMA buffers, etc.) This - * is currently overcomed by allocating these buffers directly in AGP memory - * when available, or by allocating a pool with a single buffer and with a - * size different of the regular client buffers. - * - It doesn't allow to be two different pools with the same log2 of the - * buffers size making impossible, e.g., to have to pools of buffers: one - * private and one public. - * - The high/low water mark is hardly used and the freelist should be - * redesigned to be more useful for all drivers. */ /* @@ -59,7 +46,7 @@ typedef struct drm_pool drm_pool_t; /** * A buffer of the DMA buffer pool. * - * \sa drm_pool. + * This structure holds individual buffer information. See also drm_pool. */ struct drm_pool_buffer { void * cpuaddr; /**< kernel virtual address */ @@ -69,7 +56,14 @@ struct drm_pool_buffer { /** * DMA buffer pool. * - * \sa drm_pool_buffer. + * This structure stores information about an homogeneous pool of buffers. See + * also drm_pool_buffer. + * + * It only provides the basic information. This structure can be extended by + * composition. See drm_pool_pci, drm_pool_agp, and drm_pool_sg for examples. + * + * See drm_freelist2 for a convinient and extensible way to manage a buffer + * pool. */ struct drm_pool { size_t count; /**< number of buffers */ @@ -86,11 +80,11 @@ struct drm_pool { /** \name Free-list management */ /*@{*/ -typedef struct drm_freelist2_entrys drm_freelist2_entrys_t; +typedef struct drm_freelist2_entry drm_freelist2_entry_t; typedef struct drm_freelist2 drm_freelist2_t; /** - * An entrys in a freelist. + * An entryin a freelist. * * This structure can be extended by passing to drm_freelist2_init a stride * value greater than the size of this structure. @@ -100,7 +94,7 @@ typedef struct drm_freelist2 drm_freelist2_t; * \author Based on Leif Delgass's original freelist code for the Mach64 * driver. */ -struct drm_freelist2_entrys { +struct drm_freelist2_entry { struct list_head list; /**< Linux list */ drm_pool_buffer_t * buffer; /**< referred DMA buffer */ @@ -154,7 +148,7 @@ struct drm_freelist2 { /** * Stamp of the last processed buffer. * - * \sa drm_free_list2_entrys::stamp. + * \sa drm_free_list2_entry::stamp. */ unsigned long last_stamp; @@ -168,6 +162,7 @@ struct drm_freelist2 { /*@}*/ +#if 0 /** \name Deprecated structure */ /*@{*/ @@ -253,6 +248,35 @@ typedef struct drm_buf_entry { } drm_buf_entry_t; /*@}*/ +#endif + +/** + * Backward compatability buffer pools used by the addbufs_ioctl() and friends. + * + * There is one of these for each buffer size in log2. Note that there can't be + * two different pools with the same log2 of the buffers size. + */ +typedef struct drm_buf_entry { + drm_pool_t * pool; /**< the pool */ + int seg_count; + int page_order; + unsigned long * seglist; +} drm_buf_entry_t; + + + +/** + * Device buffer related data. + */ +typedef struct drm_bufs_data_t { + /** buffers, grouped by their size order for backwards compatability */ + drm_buf_entry_t bufs[DRM_MAX_ORDER + 1]; + enum { + _DRM_DMA_USE_AGP = 0x01, + _DRM_DMA_USE_SG = 0x02 + } flags; +} ; + /** \name Prototypes */ diff --git a/linux/drm_dma.h b/linux/drm_dma.h index 14d5043dc..e934f126d 100644 --- a/linux/drm_dma.h +++ b/linux/drm_dma.h @@ -57,10 +57,11 @@ typedef struct drm_queue { * DMA data. */ typedef struct drm_device_dma { - +#if 0 drm_buf_entry_t bufs[DRM_MAX_ORDER+1]; /**< buffers, grouped by their size order */ int buf_count; /**< total number of buffers */ drm_buf_t **buflist; /**< Vector of pointers into drm_device_dma::bufs */ +#endif int seg_count; int page_count; /**< number of pages */ unsigned long *pagelist; /**< page list */ diff --git a/linux/drm_memory_tmp.h b/linux/drm_mem.c index c633079aa..60e329125 100644 --- a/linux/drm_memory_tmp.h +++ b/linux/drm_mem.c @@ -35,6 +35,106 @@ #include <linux/config.h> #include "drmP.h" + +/** \name Regular memory allocation */ +/*@{*/ + +/** Wrapper around kmalloc() */ +void *drm_alloc(size_t size) +{ + return kmalloc(size, GFP_KERNEL); +} + +/** Wrapper around kmalloc() and kfree() */ +void *drm_realloc(void *ptrt, size_t oldsize, size_t size) +{ + void *pt; + + if (!(pt = kmalloc(size, GFP_KERNEL))) return NULL; + if (oldpt && oldsize) { + memcpy(pt, oldpt, oldsize); + kfree(oldpt); + } + return pt; +} + +/** Wrapper around kfree() */ +void drm_free(void *ptr) +{ + kfree(pt); +} + +/*@}*/ + + +/** \name Page allocation */ +/*@{*/ + +/** + * Allocate pages. + * + * \param order size order. + * \return page address on success, or zero on failure. + * + * Allocate and reserve free pages. + */ +unsigned long drm_alloc_pages(int order) +{ + unsigned long address; + unsigned long bytes = PAGE_SIZE << order; + unsigned long addr; + unsigned int sz; + + address = __get_free_pages(GFP_KERNEL, order); + if (!address) + return 0; + + /* Zero */ + memset((void *)address, 0, bytes); + + /* Reserve */ + for (addr = address, sz = bytes; + sz > 0; + addr += PAGE_SIZE, sz -= PAGE_SIZE) { + SetPageReserved(virt_to_page(addr)); + } + + return address; +} + +/** + * Free pages. + * + * \param address address of the pages to free. + * \param order size order. + * + * Unreserve and free pages allocated by alloc_pages(). + */ +void drm_free_pages(unsigned long address, int order) +{ + unsigned long bytes = PAGE_SIZE << order; + unsigned long addr; + unsigned int sz; + + if (!address) + return; + + /* Unreserve */ + for (addr = address, sz = bytes; + sz > 0; + addr += PAGE_SIZE, sz -= PAGE_SIZE) { + ClearPageReserved(virt_to_page(addr)); + } + + free_pages(address, order); +} + +/*@}*/ + + +/** \name Memory mapping */ +/*@{*/ + /* Need the 4-argument version of vmap(). */ #if __REALLY_HAVE_AGP && defined(VMAP_4_ARGS) @@ -59,8 +159,10 @@ # define flush_tlb_kernel_range(s,e) flush_tlb_all() #endif -/* - * Find the drm_map that covers the range [offset, offset+size). + + +/** + * Find the drm_map that covers the range [offset, offset+size]. */ static inline drm_map_t * drm_lookup_map (unsigned long offset, unsigned long size, drm_device_t *dev) @@ -189,106 +291,4 @@ static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *d iounmap(pt); } -/** Wrapper around kmalloc() */ -void *DRM(alloc)(size_t size, int area) -{ - return kmalloc(size, GFP_KERNEL); -} - -/** Wrapper around kmalloc() and kfree() */ -void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size, int area) -{ - void *pt; - - if (!(pt = kmalloc(size, GFP_KERNEL))) return NULL; - if (oldpt && oldsize) { - memcpy(pt, oldpt, oldsize); - kfree(oldpt); - } - return pt; -} - -/** Wrapper around kfree() */ -void DRM(free)(void *pt, size_t size, int area) -{ - kfree(pt); -} - -/** - * Allocate pages. - * - * \param order size order. - * \param area memory area. (Not used.) - * \return page address on success, or zero on failure. - * - * Allocate and reserve free pages. - */ -unsigned long DRM(alloc_pages)(int order, int area) -{ - unsigned long address; - unsigned long bytes = PAGE_SIZE << order; - unsigned long addr; - unsigned int sz; - - address = __get_free_pages(GFP_KERNEL, order); - if (!address) - return 0; - - /* Zero */ - memset((void *)address, 0, bytes); - - /* Reserve */ - for (addr = address, sz = bytes; - sz > 0; - addr += PAGE_SIZE, sz -= PAGE_SIZE) { - SetPageReserved(virt_to_page(addr)); - } - - return address; -} - -/** - * Free pages. - * - * \param address address of the pages to free. - * \param order size order. - * \param area memory area. (Not used.) - * - * Unreserve and free pages allocated by alloc_pages(). - */ -void DRM(free_pages)(unsigned long address, int order, int area) -{ - unsigned long bytes = PAGE_SIZE << order; - unsigned long addr; - unsigned int sz; - - if (!address) - return; - - /* Unreserve */ - for (addr = address, sz = bytes; - sz > 0; - addr += PAGE_SIZE, sz -= PAGE_SIZE) { - ClearPageReserved(virt_to_page(addr)); - } - - free_pages(address, order); -} - -/** Wrapper around drm_ioremap() */ -void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev) -{ - return drm_ioremap(offset, size, dev); -} - -/** Wrapper around drm_ioremap_nocache() */ -void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev) -{ - return drm_ioremap_nocache(offset, size, dev); -} - -/** Wrapper around drm_iounmap() */ -void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev) -{ - drm_ioremapfree(pt, size, dev); -} +/*@}*/ diff --git a/linux/drm_memory.h b/linux/drm_memory.h deleted file mode 100644 index 5ccaa5b05..000000000 --- a/linux/drm_memory.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * \file drm_memory.h - * Memory management wrappers for DRM - * - * \author Rickard E. (Rik) Faith <faith@valinux.com> - * \author Gareth Hughes <gareth@valinux.com> - */ - -/* - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, 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 - * VA LINUX SYSTEMS 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. - */ - - -#ifndef _DRM_MEMORY_H_ -#define _DRM_MEMORY_H_ - - -/** \name Prototypes */ -/*@{*/ - -extern void *DRM(alloc)(size_t size, int area); -extern void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size, int area); -extern void DRM(free)(void *pt, size_t size, int area); -extern unsigned long DRM(alloc_pages)(int order, int area); -extern void DRM(free_pages)(unsigned long address, int order, int area); -extern void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev); -extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev); -extern void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev); - -/*@}*/ - - -#endif /* !_DRM_MEMORY_H_ */ diff --git a/linux/drm_pci_tmp.h b/linux/drm_pci.c index 4651ccdce..b6653d1fd 100644 --- a/linux/drm_pci_tmp.h +++ b/linux/drm_pci.c @@ -1,11 +1,9 @@ /** * \file drm_pci_tmp.h - * ioctl's to manage PCI memory + * PCI consistent memory allocation. * * \warning These interfaces aren't stable yet. * - * \todo Implement the remaining ioctl's for the PCI pools. - * \todo Add support to map these buffers. * \todo The wrappers here are so thin that they would be better off inlined.. * * \author José Fonseca <jrfonseca@tungstengraphics.com> @@ -47,7 +45,7 @@ /** * Allocate a PCI consistent memory block, for DMA. */ -void * DRM(pci_alloc)( drm_device_t *dev, size_t size, +void * drm_pci_alloc( drm_device_t *dev, size_t size, dma_addr_t *busaddr ) { return pci_alloc_consistent( dev->pdev, size, busaddr ); @@ -56,7 +54,7 @@ void * DRM(pci_alloc)( drm_device_t *dev, size_t size, /** * Free a PCI consistent memory block. */ -void DRM(pci_free)( drm_device_t *dev, size_t size, void *cpuaddr, +void drm_pci_free( drm_device_t *dev, size_t size, void *cpuaddr, dma_addr_t busaddr ) { DRM_DEBUG( "%s\n", __FUNCTION__ ); @@ -68,7 +66,13 @@ void DRM(pci_free)( drm_device_t *dev, size_t size, void *cpuaddr, /**********************************************************************/ -/** \name PCI memory pool */ +/** + * \name PCI memory pool + * + * These are low level abstractions of the OS primitives. Don't call these + * directly from the drivers. Use drm_pool_pci_alloc() and drm_pool_free() + * instead. + */ /*@{*/ /** @@ -80,20 +84,16 @@ void DRM(pci_free)( drm_device_t *dev, size_t size, void *cpuaddr, * function to ease porting to other OS's. More functionality can be exposed * later if actually required by the drivers. */ -void *DRM(pci_pool_create)( drm_device_t *dev, size_t size, size_t align ) +void *drm_pci_pool_create( drm_device_t *dev, size_t size, size_t align ) { - DRM_DEBUG( "%s\n", __FUNCTION__ ); - return pci_pool_create( "DRM", dev->pdev, size, align, 0, 0); } /** * Destroy a pool of PCI consistent memory blocks. */ -void DRM(pci_pool_destroy)( drm_device_t *dev, void *entry ) +void drm_pci_pool_destroy( drm_device_t *dev, void *entry ) { - DRM_DEBUG( "%s\n", __FUNCTION__ ); - pci_pool_destroy( (struct pci_pool *)entry ); } @@ -102,20 +102,16 @@ void DRM(pci_pool_destroy)( drm_device_t *dev, void *entry ) * * \return the virtual address of a block on success, or NULL on failure. */ -void *DRM(pci_pool_alloc)( void *entry, dma_addr_t *busaddr ) +void *drm_pci_pool_alloc( void *entry, dma_addr_t *busaddr ) { - DRM_DEBUG( "%s\n", __FUNCTION__ ); - return pci_pool_alloc( (struct pci_pool *)entry, 0, busaddr ); } /** * Free a block back into a PCI consistent memory block pool. */ -void DRM(pci_pool_free)( void *entry, void *cpuaddr, dma_addr_t busaddr ) +void drm_pci_pool_free( void *entry, void *cpuaddr, dma_addr_t busaddr ) { - DRM_DEBUG( "%s\n", __FUNCTION__ ); - pci_pool_free( (struct pci_pool *)entry, cpuaddr, busaddr ); } @@ -128,7 +124,7 @@ void DRM(pci_pool_free)( void *entry, void *cpuaddr, dma_addr_t busaddr ) /** \name Ioctl's */ /*@{*/ -int DRM(pci_alloc_ioctl)( struct inode *inode, struct file *filp, +int drm_pci_alloc_ioctl( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ) { drm_file_t *priv = filp->private_data; @@ -143,17 +139,17 @@ int DRM(pci_alloc_ioctl)( struct inode *inode, struct file *filp, sizeof(request) ) ) return -EFAULT; - entry = DRM(alloc)( sizeof(*entry), DRM_MEM_DRIVER ); + entry = drm_alloc( sizeof(*entry), DRM_MEM_DRIVER ); if ( !entry ) return -ENOMEM; memset( entry, 0, sizeof(*entry) ); - entry->cpuaddr = DRM(pci_alloc)( dev, request.size, + entry->cpuaddr = drm_pci_alloc( dev, request.size, &entry->busaddr ); if ( !entry->cpuaddr ) { - DRM(free)( entry, sizeof(*entry), DRM_MEM_DRIVER ); + drm_free( entry ); return -ENOMEM; } @@ -163,9 +159,9 @@ int DRM(pci_alloc_ioctl)( struct inode *inode, struct file *filp, if ( copy_to_user( (drm_pci_mem_ioctl_t *)arg, &request, sizeof(request) ) ) { - DRM(pci_free)( dev, entry->size, entry->cpuaddr, + drm_pci_free( dev, entry->size, entry->cpuaddr, entry->busaddr ); - DRM(free)( entry, sizeof(*entry), DRM_MEM_DRIVER ); + drm_free( entry ); return -EFAULT; } @@ -174,7 +170,7 @@ int DRM(pci_alloc_ioctl)( struct inode *inode, struct file *filp, return 0; } -int DRM(pci_free_ioctl)( struct inode *inode, struct file *filp, +int drm_pci_free_ioctl( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ) { drm_file_t *priv = filp->private_data; @@ -195,9 +191,9 @@ int DRM(pci_free_ioctl)( struct inode *inode, struct file *filp, entry = list_entry(ptr, drm_pci_mem_t, list); if( entry->busaddr == request.busaddr ) { list_del(ptr); - DRM(pci_free)( dev, entry->size, entry->cpuaddr, + drm_pci_free( dev, entry->size, entry->cpuaddr, entry->busaddr ); - DRM(free)( entry, sizeof(*entry), DRM_MEM_DRIVER ); + drm_free( entry ); return 0; } } @@ -214,7 +210,7 @@ int DRM(pci_free_ioctl)( struct inode *inode, struct file *filp, /** * Called on driver exit to free the PCI memory allocated by userspace. */ -void DRM(pci_cleanup)( drm_device_t *dev ) +void drm_pci_cleanup( drm_device_t *dev ) { struct list_head *ptr, *tmp; drm_pci_mem_t *entry; @@ -225,9 +221,9 @@ void DRM(pci_cleanup)( drm_device_t *dev ) { entry = list_entry(ptr, drm_pci_mem_t, list); list_del(ptr); - DRM(pci_free)( dev, entry->size, entry->cpuaddr, + drm_pci_free( dev, entry->size, entry->cpuaddr, entry->busaddr ); - DRM(free)( entry, sizeof(*entry), DRM_MEM_DRIVER ); + drm_free( entry ); } } diff --git a/linux/drm_sg_tmp.h b/linux/drm_sg.c index 95cb1fc7e..c366cca8a 100644 --- a/linux/drm_sg_tmp.h +++ b/linux/drm_sg.c @@ -51,7 +51,7 @@ * * \param entry scatter/gather memory entry to free, as returned by sg_alloc(). */ -void DRM(sg_free)( drm_sg_mem_t *entry ) +void drm_sg_free( drm_sg_mem_t *entry ) { struct page *page; int i; @@ -64,13 +64,13 @@ void DRM(sg_free)( drm_sg_mem_t *entry ) vfree( entry->virtual ); - DRM(free)( entry->busaddr, + drm_free( entry->busaddr, entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES ); - DRM(free)( entry->pagelist, + drm_free( entry->pagelist, entry->pages * sizeof(*entry->pagelist), DRM_MEM_PAGES ); - DRM(free)( entry, + drm_free( entry, sizeof(*entry), DRM_MEM_SGLISTS ); } @@ -81,14 +81,14 @@ void DRM(sg_free)( drm_sg_mem_t *entry ) * \param size size of memory to allocate. * \return pointer to a drm_sg_mem structure on success or NULL on failure. */ -drm_sg_mem_t * DRM(sg_alloc)( unsigned long size ) +drm_sg_mem_t * drm_sg_alloc( unsigned long size ) { drm_sg_mem_t *entry; unsigned long pages, i, j; DRM_DEBUG( "%s\n", __FUNCTION__ ); - entry = DRM(alloc)( sizeof(*entry), DRM_MEM_SGLISTS ); + entry = drm_alloc( sizeof(*entry), DRM_MEM_SGLISTS ); if ( !entry ) return NULL; @@ -98,22 +98,22 @@ drm_sg_mem_t * DRM(sg_alloc)( unsigned long size ) DRM_DEBUG( "sg size=%ld pages=%ld\n", size, pages ); entry->pages = pages; - entry->pagelist = DRM(alloc)( pages * sizeof(*entry->pagelist), + entry->pagelist = drm_alloc( pages * sizeof(*entry->pagelist), DRM_MEM_PAGES ); if ( !entry->pagelist ) { - DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS ); + drm_free( entry, sizeof(*entry), DRM_MEM_SGLISTS ); return NULL; } memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist)); - entry->busaddr = DRM(alloc)( pages * sizeof(*entry->busaddr), + entry->busaddr = drm_alloc( pages * sizeof(*entry->busaddr), DRM_MEM_PAGES ); if ( !entry->busaddr ) { - DRM(free)( entry->pagelist, + drm_free( entry->pagelist, entry->pages * sizeof(*entry->pagelist), DRM_MEM_PAGES ); - DRM(free)( entry, + drm_free( entry, sizeof(*entry), DRM_MEM_SGLISTS ); return NULL; @@ -122,13 +122,13 @@ drm_sg_mem_t * DRM(sg_alloc)( unsigned long size ) entry->virtual = vmalloc_32( pages << PAGE_SHIFT ); if ( !entry->virtual ) { - DRM(free)( entry->busaddr, + drm_free( entry->busaddr, entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES ); - DRM(free)( entry->pagelist, + drm_free( entry->pagelist, entry->pages * sizeof(*entry->pagelist), DRM_MEM_PAGES ); - DRM(free)( entry, + drm_free( entry, sizeof(*entry), DRM_MEM_SGLISTS ); return NULL; @@ -191,7 +191,7 @@ drm_sg_mem_t * DRM(sg_alloc)( unsigned long size ) return entry; failed: - DRM(sg_free)( entry ); + drm_sg_free( entry ); return NULL; } @@ -220,7 +220,7 @@ drm_sg_mem_t * DRM(sg_alloc)( unsigned long size ) * \param arg user argument, pointing to a drm_scatter_gather structure. * \return zero on success or a negative number on failure. */ -int DRM(sg_alloc_ioctl)( struct inode *inode, struct file *filp, +int drm_sg_alloc_ioctl( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ) { drm_file_t *priv = filp->private_data; @@ -238,7 +238,7 @@ int DRM(sg_alloc_ioctl)( struct inode *inode, struct file *filp, sizeof(request) ) ) return -EFAULT; - entry = DRM(sg_alloc)( request.size ); + entry = drm_sg_alloc( request.size ); if ( !entry ) return -ENOMEM; @@ -247,7 +247,7 @@ int DRM(sg_alloc_ioctl)( struct inode *inode, struct file *filp, if ( copy_to_user( (drm_scatter_gather_t *)arg, &request, sizeof(request) ) ) { - DRM(sg_free)( entry ); + drm_sg_free( entry ); return -EFAULT; } @@ -264,7 +264,7 @@ int DRM(sg_alloc_ioctl)( struct inode *inode, struct file *filp, * \param arg user argument, pointing to a drm_scatter_gather structure. * \return zero on success or a negative number on failure. */ -int DRM(sg_free_ioctl)( struct inode *inode, struct file *filp, +int drm_sg_free_ioctl( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ) { drm_file_t *priv = filp->private_data; @@ -285,7 +285,7 @@ int DRM(sg_free_ioctl)( struct inode *inode, struct file *filp, DRM_DEBUG( "sg free virtual = %p\n", entry->virtual ); - DRM(sg_free)( entry ); + drm_sg_free( entry ); return 0; } @@ -297,10 +297,10 @@ int DRM(sg_free_ioctl)( struct inode *inode, struct file *filp, * Called by takedown() to free the scatter/gather memory resources associated * with a given device, i.e., to free drm_device_t::sg. */ -void DRM(sg_cleanup)(drm_device_t *dev) +void drm_sg_cleanup(drm_device_t *dev) { if ( dev->sg ) { - DRM(sg_free)( dev->sg ); + drm_sg_free( dev->sg ); dev->sg = NULL; } } diff --git a/linux/drm_sg.h b/linux/drm_sg.h index afd80ef06..16f50f42f 100644 --- a/linux/drm_sg.h +++ b/linux/drm_sg.h @@ -54,11 +54,11 @@ typedef struct drm_sg_mem { /** \name Prototypes */ /*@{*/ -extern void DRM(sg_free)( drm_sg_mem_t *entry ); -extern drm_sg_mem_t * DRM(sg_alloc)( unsigned long size ); -extern int DRM(sg_alloc_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern int DRM(sg_free_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern void DRM(sg_cleanup)(drm_device_t *dev); +extern void drm_sg_free( drm_sg_mem_t *entry ); +extern drm_sg_mem_t * drm_sg_alloc( unsigned long size ); +extern int drm_sg_alloc_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern int drm_sg_free_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern void drm_sg_cleanup(drm_device_t *dev); /*@}*/ |