summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2002-08-27 12:16:32 +0000
committerKeith Whitwell <keith@tungstengraphics.com>2002-08-27 12:16:32 +0000
commite45c84ba9166526eb18517d82234e128c1476290 (patch)
treec5bf1b2919ab2f82deeba48cb0c7a3396ba5da3b
parent5e81d590d557672376795011b9d78e93d10e2f7f (diff)
initial pass at allocator
-rw-r--r--bsd/drm_linux.h159
-rw-r--r--shared-core/radeon_mem.c184
-rw-r--r--shared/radeon_mem.c184
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;
+}