drm_memory.c revision 1.20
1/*-
2 *Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
3 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Authors:
26 *    Rickard E. (Rik) Faith <faith@valinux.com>
27 *    Gareth Hughes <gareth@valinux.com>
28 *
29 */
30
31/** @file drm_memory.c
32 * Wrappers for kernel memory allocation routines, and MTRR management support.
33 *
34 * This file previously implemented a memory consumption tracking system using
35 * the "area" argument for various different types of allocations, but that
36 * has been stripped out for now.
37 */
38
39#include "drmP.h"
40
41void*
42drm_alloc(size_t size)
43{
44	return (malloc(size, M_DRM, M_NOWAIT));
45}
46
47void *
48drm_calloc(size_t nmemb, size_t size)
49{
50	if (nmemb == 0 || SIZE_MAX / nmemb < size)
51		return (NULL);
52	else
53		return malloc(size * nmemb, M_DRM, M_NOWAIT | M_ZERO);
54}
55
56void *
57drm_realloc(void *oldpt, size_t oldsize, size_t size)
58{
59	void *pt;
60
61	pt = malloc(size, M_DRM, M_NOWAIT);
62	if (pt == NULL)
63		return NULL;
64	if (oldpt && oldsize) {
65		memcpy(pt, oldpt, min(oldsize, size));
66		free(oldpt, M_DRM);
67	}
68	return pt;
69}
70
71void
72drm_free(void *pt)
73{
74	if (pt != NULL)
75		free(pt, M_DRM);
76}
77
78/* Inline replacements for DRM_IOREMAP macros */
79void
80drm_core_ioremap(struct drm_local_map *map, struct drm_device *dev)
81{
82	DRM_DEBUG("offset: 0x%x size: 0x%x type: %d\n", map->offset, map->size,
83	    map->type);
84
85	/* default to failure. */
86	map->handle = 0;
87
88	if (map->type == _DRM_AGP || map->type == _DRM_FRAME_BUFFER) {
89	/*
90	 * there can be multiple agp maps in the same BAR, agp also
91	 * quite possibly isn't the same as the vga device, just try
92	 * to map it.
93	 */
94		DRM_DEBUG("AGP map\n");
95		map->bst = dev->bst;
96		if (bus_space_map(map->bst, map->offset,
97		    map->size, BUS_SPACE_MAP_LINEAR, &map->bsh)) {
98			DRM_ERROR("ioremap fail\n");
99			return;
100		}
101		/* handles are still supposed to be kernel virtual addresses */
102		map->handle = bus_space_vaddr(map->bst, map->bsh);
103	}
104}
105
106void
107drm_core_ioremapfree(struct drm_local_map *map)
108{
109	if (map->handle && map->size && (map->type == _DRM_AGP ||
110	    map->type == _DRM_FRAME_BUFFER)) {
111		bus_space_unmap(map->bst, map->bsh, map->size);
112		map->handle = 0;
113	}
114}
115
116int
117drm_mtrr_add(unsigned long offset, size_t size, int flags)
118{
119#ifndef DRM_NO_MTRR
120	int act;
121	struct mem_range_desc mrdesc;
122
123	mrdesc.mr_base = offset;
124	mrdesc.mr_len = size;
125	mrdesc.mr_flags = flags;
126	act = MEMRANGE_SET_UPDATE;
127	strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner));
128	return mem_range_attr_set(&mrdesc, &act);
129#else
130	return 0;
131#endif
132}
133
134int
135drm_mtrr_del(int handle, unsigned long offset, size_t size, int flags)
136{
137#ifndef DRM_NO_MTRR
138	int act;
139	struct mem_range_desc mrdesc;
140
141	mrdesc.mr_base = offset;
142	mrdesc.mr_len = size;
143	mrdesc.mr_flags = flags;
144	act = MEMRANGE_SET_REMOVE;
145	strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner));
146	return mem_range_attr_set(&mrdesc, &act);
147#else
148	return 0;
149#endif
150}
151