diff options
author | Keith Whitwell <keith@tungstengraphics.com> | 2002-08-27 12:16:32 +0000 |
---|---|---|
committer | Keith Whitwell <keith@tungstengraphics.com> | 2002-08-27 12:16:32 +0000 |
commit | e45c84ba9166526eb18517d82234e128c1476290 (patch) | |
tree | c5bf1b2919ab2f82deeba48cb0c7a3396ba5da3b | |
parent | 5e81d590d557672376795011b9d78e93d10e2f7f (diff) |
initial pass at allocator
-rw-r--r-- | bsd/drm_linux.h | 159 | ||||
-rw-r--r-- | shared-core/radeon_mem.c | 184 | ||||
-rw-r--r-- | shared/radeon_mem.c | 184 |
3 files changed, 368 insertions, 159 deletions
diff --git a/bsd/drm_linux.h b/bsd/drm_linux.h deleted file mode 100644 index 4c928192..00000000 --- a/bsd/drm_linux.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2000 by Coleman Kane <cokane@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Gardner Buchanan. - * 4. The name of Gardner Buchanan may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/tdfx/tdfx_linux.h,v 1.4 2000/08/22 05:57:55 marcel Exp $ - */ - -/* FIXME: There are IOCTLS to merge in here, see drm.h*/ - -/* Query IOCTLs */ -/* XFree86 4.1.x DRI support */ - -#define LINUX_DRM_IOCTL_VERSION 0x6400 -#define LINUX_DRM_IOCTL_GET_UNIQUE 0x6401 -#define LINUX_DRM_IOCTL_GET_MAGIC 0x6402 -#define LINUX_DRM_IOCTL_IRQ_BUSID 0x6403 -#define LINUX_DRM_IOCTL_GET_MAP 0x6404 -#define LINUX_DRM_IOCTL_GET_CLIENT 0x6405 -#define LINUX_DRM_IOCTL_GET_STATS 0x6406 - -#define LINUX_DRM_IOCTL_SET_UNIQUE 0x6410 -#define LINUX_DRM_IOCTL_AUTH_MAGIC 0x6411 -#define LINUX_DRM_IOCTL_BLOCK 0x6412 -#define LINUX_DRM_IOCTL_UNBLOCK 0x6413 -#define LINUX_DRM_IOCTL_CONTROL 0x6414 -#define LINUX_DRM_IOCTL_ADD_MAP 0x6415 -#define LINUX_DRM_IOCTL_ADD_BUFS 0x6416 -#define LINUX_DRM_IOCTL_MARK_BUFS 0x6417 -#define LINUX_DRM_IOCTL_INFO_BUFS 0x6418 -#define LINUX_DRM_IOCTL_MAP_BUFS 0x6419 -#define LINUX_DRM_IOCTL_FREE_BUFS 0x641a - -#define LINUX_DRM_IOCTL_RM_MAP 0x641b - -#define LINUX_DRM_IOCTL_SET_SAREA_CTX 0x641c -#define LINUX_DRM_IOCTL_GET_SAREA_CTX 0x641d - -#define LINUX_DRM_IOCTL_ADD_CTX 0x6420 -#define LINUX_DRM_IOCTL_RM_CTX 0x6421 -#define LINUX_DRM_IOCTL_MOD_CTX 0x6422 -#define LINUX_DRM_IOCTL_GET_CTX 0x6423 -#define LINUX_DRM_IOCTL_SWITCH_CTX 0x6424 -#define LINUX_DRM_IOCTL_NEW_CTX 0x6425 -#define LINUX_DRM_IOCTL_RES_CTX 0x6426 -#define LINUX_DRM_IOCTL_ADD_DRAW 0x6427 -#define LINUX_DRM_IOCTL_RM_DRAW 0x6428 -#define LINUX_DRM_IOCTL_DMA 0x6429 -#define LINUX_DRM_IOCTL_LOCK 0x642a -#define LINUX_DRM_IOCTL_UNLOCK 0x642b -#define LINUX_DRM_IOCTL_FINISH 0x642c - -#define LINUX_DRM_IOCTL_AGP_ACQUIRE 0x6430 -#define LINUX_DRM_IOCTL_AGP_RELEASE 0x6431 -#define LINUX_DRM_IOCTL_AGP_ENABLE 0x6432 -#define LINUX_DRM_IOCTL_AGP_INFO 0x6433 -#define LINUX_DRM_IOCTL_AGP_ALLOC 0x6434 -#define LINUX_DRM_IOCTL_AGP_FREE 0x6435 -#define LINUX_DRM_IOCTL_AGP_BIND 0x6436 -#define LINUX_DRM_IOCTL_AGP_UNBIND 0x6437 - -#define LINUX_DRM_IOCTL_SG_ALLOC 0x6438 -#define LINUX_DRM_IOCTL_SG_FREE 0x6439 - -/* MGA specific ioctls */ -#define LINUX_DRM_IOCTL_MGA_INIT 0x6440 -#define LINUX_DRM_IOCTL_MGA_FLUSH 0x6441 -#define LINUX_DRM_IOCTL_MGA_RESET 0x6442 -#define LINUX_DRM_IOCTL_MGA_SWAP 0x6443 -#define LINUX_DRM_IOCTL_MGA_CLEAR 0x6444 -#define LINUX_DRM_IOCTL_MGA_VERTEX 0x6445 -#define LINUX_DRM_IOCTL_MGA_INDICES 0x6446 -#define LINUX_DRM_IOCTL_MGA_ILOAD 0x6447 -#define LINUX_DRM_IOCTL_MGA_BLIT 0x6448 - -/* i810 specific ioctls */ -#define LINUX_DRM_IOCTL_I810_INIT 0x6440 -#define LINUX_DRM_IOCTL_I810_VERTEX 0x6441 -#define LINUX_DRM_IOCTL_I810_CLEAR 0x6442 -#define LINUX_DRM_IOCTL_I810_FLUSH 0x6443 -#define LINUX_DRM_IOCTL_I810_GETAGE 0x6444 -#define LINUX_DRM_IOCTL_I810_GETBUF 0x6445 -#define LINUX_DRM_IOCTL_I810_SWAP 0x6446 -#define LINUX_DRM_IOCTL_I810_COPY 0x6447 -#define LINUX_DRM_IOCTL_I810_DOCOPY 0x6448 - -/* I830 specific ioctls */ -#define LINUX_DRM_IOCTL_I830_INIT 0x6440 -#define LINUX_DRM_IOCTL_I830_VERTEX 0x6441 -#define LINUX_DRM_IOCTL_I830_CLEAR 0x6442 -#define LINUX_DRM_IOCTL_I830_FLUSH 0x6443 -#define LINUX_DRM_IOCTL_I830_GETAGE 0x6444 -#define LINUX_DRM_IOCTL_I830_GETBUF 0x6445 -#define LINUX_DRM_IOCTL_I830_SWAP 0x6446 -#define LINUX_DRM_IOCTL_I830_COPY 0x6447 -#define LINUX_DRM_IOCTL_I830_DOCOPY 0x6448 - -/* Rage 128 specific ioctls */ -#define LINUX_DRM_IOCTL_R128_INIT 0x6440 -#define LINUX_DRM_IOCTL_R128_CCE_START 0x6441 -#define LINUX_DRM_IOCTL_R128_CCE_STOP 0x6442 -#define LINUX_DRM_IOCTL_R128_CCE_RESET 0x6443 -#define LINUX_DRM_IOCTL_R128_CCE_IDLE 0x6444 -#define LINUX_DRM_IOCTL_R128_RESET 0x6446 -#define LINUX_DRM_IOCTL_R128_SWAP 0x6447 -#define LINUX_DRM_IOCTL_R128_CLEAR 0x6448 -#define LINUX_DRM_IOCTL_R128_VERTEX 0x6449 -#define LINUX_DRM_IOCTL_R128_INDICES 0x644a -#define LINUX_DRM_IOCTL_R128_BLIT 0x644b -#define LINUX_DRM_IOCTL_R128_DEPTH 0x644c -#define LINUX_DRM_IOCTL_R128_STIPPLE 0x644d -#define LINUX_DRM_IOCTL_R128_INDIRECT 0x644f -#define LINUX_DRM_IOCTL_R128_FULLSCREEN 0x6450 - -/* Radeon specific ioctls */ -#define LINUX_DRM_IOCTL_RADEON_CP_INIT 0x6440 -#define LINUX_DRM_IOCTL_RADEON_CP_START 0x6441 -#define LINUX_DRM_IOCTL_RADEON_CP_STOP 0x6442 -#define LINUX_DRM_IOCTL_RADEON_CP_RESET 0x6443 -#define LINUX_DRM_IOCTL_RADEON_CP_IDLE 0x6444 -#define LINUX_DRM_IOCTL_RADEON_RESET 0x6445 -#define LINUX_DRM_IOCTL_RADEON_FULLSCREEN 0x6446 -#define LINUX_DRM_IOCTL_RADEON_SWAP 0x6447 -#define LINUX_DRM_IOCTL_RADEON_CLEAR 0x6448 -#define LINUX_DRM_IOCTL_RADEON_VERTEX 0x6449 -#define LINUX_DRM_IOCTL_RADEON_INDICES 0x644a -#define LINUX_DRM_IOCTL_RADEON_STIPPLE 0x644c -#define LINUX_DRM_IOCTL_RADEON_INDIRECT 0x644d -#define LINUX_DRM_IOCTL_RADEON_TEXTURE 0x644e -#define LINUX_DRM_IOCTL_RADEON_VERTEX2 0x644f - -/* card specific ioctls may increase the DRM_MAX */ -#define LINUX_IOCTL_DRM_MIN LINUX_DRM_IOCTL_VERSION -#define LINUX_IOCTL_DRM_MAX 0x64ff diff --git a/shared-core/radeon_mem.c b/shared-core/radeon_mem.c new file mode 100644 index 00000000..4d91cefd --- /dev/null +++ b/shared-core/radeon_mem.c @@ -0,0 +1,184 @@ +/* radeon_state.c -- State support for Radeon -*- linux-c -*- + * + * Copyright 2000 VA Linux Systems, Inc., Fremont, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "radeon.h" +#include "drmP.h" +#include "drm.h" +#include "radeon_drm.h" +#include "radeon_drv.h" + +/* Very simple allocator for agp memory, working on a static range + * already mapped into each client's address space. + * + * TODO: dynamically grow region, make regions truely private to each + * client, etc. Make work with FB memory as well as agp. + */ +struct mem_block { + struct mem_block *next; + struct mem_block *prev; + int start; + int size; + int pid; /* 0: free, -1: heap, other: real pids */ +}; + + +static int init(struct mem_block *heap, int start, int size) +{ + struct mem_block *blocks = malloc(sizeof(*blocks)); + + if (!blocks) + return -ENOMEM; + + blocks->start = start; + blocks->size = size; + blocks->pid = 0; + blocks->next = blocks->prev = heap; + + memset( heap, 0, sizeof(*heap) ); + heap->pid = -1; + heap->next = heap->prev = blocks; + return 0; +} + + +static struct mem_block *split_block(struct mem_block *p, int start, int size, + int pid ) +{ + /* Maybe cut off the start of an existing block */ + if (start > p->start) { + struct mem_block *newblock = malloc(sizeof(*newblock)); + if (!newblock) + goto out; + newblock->start = start; + newblock->size = p->size - (start - p->start); + newblock->pid = 0; + newblock->next = p->next; + newblock->prev = p; + p->next->prev = newblock; + p->next = newblock; + p->size -= newblock->size; + p = newblock; + } + + /* Maybe cut off the end of an existing block */ + if (size < p->size) { + struct mem_block *newblock = malloc(sizeof(*newblock)); + if (!newblock) + goto out; + newblock->start = start + size; + newblock->size = p->size - size; + newblock->pid = 0; + newblock->next = p->next; + newblock->prev = p; + p->next->prev = newblock; + p->next = newblock; + p->size = size; + } + + out: + /* Our block is in the middle */ + p->pid = pid; + return p; +} + +static struct mem_block *alloc_block( struct mem_block *heap, int size, + int align2, int pid ) +{ + struct mem_block *p; + int mask = (1 << align2)-1; + + for (p = heap->next ; p != heap ; p = p->next) { + if (p->pid == 0) { + int start = (p->start + mask) & ~mask; + if (start + size <= p->start + p->size) + return split_block( p, start, size, pid ); + } + } + + return NULL; +} + + +static void free_block( struct mem_block *b ) +{ + p->pid = 0; + + /* Assumes a single contiguous range. Needs a special pid in + * 'heap' to stop it being subsumed. + */ + if (p->next->pid == 0) { + struct mem_block *q = p->next; + p->size += q->size; + p->next = q->next; + p->next->prev = p; + free(p); + } + + if (p->prev->pid == 0) { + struct mem_block *q = p->prev; + q->size += p->size; + q->next = p->next; + q->next->prev = q; + free(p); + } +} + +static void free_by_pid( struct mem_block *heap, int pid ) +{ + for (p = heap->next ; p != heap ; p = p->next) { + if (p->pid == pid) + p->pid = 0; + } + + /* Assumes a single contiguous range. Needs a special pid in + * 'heap' to stop it being subsumed. + */ + for (p = heap->next ; p != heap ; p = p->next) { + while (p->pid == 0 && p->next->pid == 0) { + struct mem_block *q = p->next; + p->size += q->size; + p->next = q->next; + p->next->prev = p; + free(q); + } + } +} + + +static void destroy(struct mem_block *heap) +{ + struct mem_block *heap; + + for (p = heap->next ; p != heap ; ) { + struct mem_block *q = p; + p = p->next; + free(q); + } + + heap->next = heap->prev = heap; +} diff --git a/shared/radeon_mem.c b/shared/radeon_mem.c new file mode 100644 index 00000000..4d91cefd --- /dev/null +++ b/shared/radeon_mem.c @@ -0,0 +1,184 @@ +/* radeon_state.c -- State support for Radeon -*- linux-c -*- + * + * Copyright 2000 VA Linux Systems, Inc., Fremont, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "radeon.h" +#include "drmP.h" +#include "drm.h" +#include "radeon_drm.h" +#include "radeon_drv.h" + +/* Very simple allocator for agp memory, working on a static range + * already mapped into each client's address space. + * + * TODO: dynamically grow region, make regions truely private to each + * client, etc. Make work with FB memory as well as agp. + */ +struct mem_block { + struct mem_block *next; + struct mem_block *prev; + int start; + int size; + int pid; /* 0: free, -1: heap, other: real pids */ +}; + + +static int init(struct mem_block *heap, int start, int size) +{ + struct mem_block *blocks = malloc(sizeof(*blocks)); + + if (!blocks) + return -ENOMEM; + + blocks->start = start; + blocks->size = size; + blocks->pid = 0; + blocks->next = blocks->prev = heap; + + memset( heap, 0, sizeof(*heap) ); + heap->pid = -1; + heap->next = heap->prev = blocks; + return 0; +} + + +static struct mem_block *split_block(struct mem_block *p, int start, int size, + int pid ) +{ + /* Maybe cut off the start of an existing block */ + if (start > p->start) { + struct mem_block *newblock = malloc(sizeof(*newblock)); + if (!newblock) + goto out; + newblock->start = start; + newblock->size = p->size - (start - p->start); + newblock->pid = 0; + newblock->next = p->next; + newblock->prev = p; + p->next->prev = newblock; + p->next = newblock; + p->size -= newblock->size; + p = newblock; + } + + /* Maybe cut off the end of an existing block */ + if (size < p->size) { + struct mem_block *newblock = malloc(sizeof(*newblock)); + if (!newblock) + goto out; + newblock->start = start + size; + newblock->size = p->size - size; + newblock->pid = 0; + newblock->next = p->next; + newblock->prev = p; + p->next->prev = newblock; + p->next = newblock; + p->size = size; + } + + out: + /* Our block is in the middle */ + p->pid = pid; + return p; +} + +static struct mem_block *alloc_block( struct mem_block *heap, int size, + int align2, int pid ) +{ + struct mem_block *p; + int mask = (1 << align2)-1; + + for (p = heap->next ; p != heap ; p = p->next) { + if (p->pid == 0) { + int start = (p->start + mask) & ~mask; + if (start + size <= p->start + p->size) + return split_block( p, start, size, pid ); + } + } + + return NULL; +} + + +static void free_block( struct mem_block *b ) +{ + p->pid = 0; + + /* Assumes a single contiguous range. Needs a special pid in + * 'heap' to stop it being subsumed. + */ + if (p->next->pid == 0) { + struct mem_block *q = p->next; + p->size += q->size; + p->next = q->next; + p->next->prev = p; + free(p); + } + + if (p->prev->pid == 0) { + struct mem_block *q = p->prev; + q->size += p->size; + q->next = p->next; + q->next->prev = q; + free(p); + } +} + +static void free_by_pid( struct mem_block *heap, int pid ) +{ + for (p = heap->next ; p != heap ; p = p->next) { + if (p->pid == pid) + p->pid = 0; + } + + /* Assumes a single contiguous range. Needs a special pid in + * 'heap' to stop it being subsumed. + */ + for (p = heap->next ; p != heap ; p = p->next) { + while (p->pid == 0 && p->next->pid == 0) { + struct mem_block *q = p->next; + p->size += q->size; + p->next = q->next; + p->next->prev = p; + free(q); + } + } +} + + +static void destroy(struct mem_block *heap) +{ + struct mem_block *heap; + + for (p = heap->next ; p != heap ; ) { + struct mem_block *q = p; + p = p->next; + free(q); + } + + heap->next = heap->prev = heap; +} |