1203288Srnoland/*- 2203288Srnoland * Copyright 2006 Tungsten Graphics Inc., Bismarck, ND., USA. 3203288Srnoland * All rights reserved. 4203288Srnoland * 5203288Srnoland * Permission is hereby granted, free of charge, to any person obtaining a 6203288Srnoland * copy of this software and associated documentation files (the "Software"), 7203288Srnoland * to deal in the Software without restriction, including without limitation 8203288Srnoland * the rights to use, copy, modify, merge, publish, distribute, sub license, 9203288Srnoland * and/or sell copies of the Software, and to permit persons to whom the 10203288Srnoland * Software is furnished to do so, subject to the following conditions: 11203288Srnoland * 12203288Srnoland * The above copyright notice and this permission notice (including the 13203288Srnoland * next paragraph) shall be included in all copies or substantial portions 14203288Srnoland * of the Software. 15203288Srnoland * 16203288Srnoland * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17203288Srnoland * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18203288Srnoland * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19203288Srnoland * THE AUTHORS OR COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20203288Srnoland * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21203288Srnoland * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22203288Srnoland * DEALINGS IN THE SOFTWARE. 23203288Srnoland */ 24203288Srnoland 25203288Srnoland/* 26203288Srnoland * Authors: Thomas Hellstr��m <thomas-at-tungstengraphics-dot-com> 27203288Srnoland */ 28203288Srnoland 29203288Srnoland#include <sys/cdefs.h> 30203288Srnoland__FBSDID("$FreeBSD$"); 31203288Srnoland 32203288Srnoland#include "dev/drm/drmP.h" 33203288Srnoland#include "dev/drm/via_drm.h" 34203288Srnoland#include "dev/drm/via_drv.h" 35203288Srnoland#include "dev/drm/drm_sman.h" 36203288Srnoland 37203288Srnoland#define VIA_MM_ALIGN_SHIFT 4 38203288Srnoland#define VIA_MM_ALIGN_MASK ( (1 << VIA_MM_ALIGN_SHIFT) - 1) 39203288Srnoland 40203288Srnolandint via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv) 41203288Srnoland{ 42203288Srnoland drm_via_agp_t *agp = data; 43203288Srnoland drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 44203288Srnoland int ret; 45203288Srnoland 46203288Srnoland ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_AGP, 0, 47203288Srnoland agp->size >> VIA_MM_ALIGN_SHIFT); 48203288Srnoland if (ret) { 49203288Srnoland DRM_ERROR("AGP memory manager initialisation error\n"); 50203288Srnoland return ret; 51203288Srnoland } 52203288Srnoland 53203288Srnoland dev_priv->agp_initialized = 1; 54203288Srnoland dev_priv->agp_offset = agp->offset; 55203288Srnoland 56203288Srnoland DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size); 57203288Srnoland return 0; 58203288Srnoland} 59203288Srnoland 60203288Srnolandint via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv) 61203288Srnoland{ 62203288Srnoland drm_via_fb_t *fb = data; 63203288Srnoland drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 64203288Srnoland int ret; 65203288Srnoland 66203288Srnoland ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_VIDEO, 0, 67203288Srnoland fb->size >> VIA_MM_ALIGN_SHIFT); 68203288Srnoland if (ret) { 69203288Srnoland DRM_ERROR("VRAM memory manager initialisation error\n"); 70203288Srnoland return ret; 71203288Srnoland } 72203288Srnoland 73203288Srnoland dev_priv->vram_initialized = 1; 74203288Srnoland dev_priv->vram_offset = fb->offset; 75203288Srnoland 76203288Srnoland DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size); 77203288Srnoland 78203288Srnoland return 0; 79203288Srnoland 80203288Srnoland} 81203288Srnoland 82203288Srnolandint via_final_context(struct drm_device *dev, int context) 83203288Srnoland{ 84203288Srnoland drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 85203288Srnoland 86203288Srnoland via_release_futex(dev_priv, context); 87203288Srnoland 88203288Srnoland#ifdef __linux__ 89203288Srnoland /* Linux specific until context tracking code gets ported to BSD */ 90203288Srnoland /* Last context, perform cleanup */ 91203288Srnoland if (dev->ctx_count == 1 && dev->dev_private) { 92203288Srnoland DRM_DEBUG("Last Context\n"); 93203288Srnoland drm_irq_uninstall(dev); 94203288Srnoland via_cleanup_futex(dev_priv); 95203288Srnoland via_do_cleanup_map(dev); 96203288Srnoland } 97203288Srnoland#endif 98203288Srnoland return 1; 99203288Srnoland} 100203288Srnoland 101203288Srnolandvoid via_lastclose(struct drm_device *dev) 102203288Srnoland{ 103203288Srnoland drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 104203288Srnoland 105203288Srnoland if (!dev_priv) 106203288Srnoland return; 107203288Srnoland 108203288Srnoland drm_sman_cleanup(&dev_priv->sman); 109203288Srnoland dev_priv->vram_initialized = 0; 110203288Srnoland dev_priv->agp_initialized = 0; 111203288Srnoland} 112203288Srnoland 113203288Srnolandint via_mem_alloc(struct drm_device *dev, void *data, 114203288Srnoland struct drm_file *file_priv) 115203288Srnoland{ 116203288Srnoland drm_via_mem_t *mem = data; 117203288Srnoland int retval = 0; 118203288Srnoland struct drm_memblock_item *item; 119203288Srnoland drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 120203288Srnoland unsigned long tmpSize; 121203288Srnoland 122203288Srnoland if (mem->type > VIA_MEM_AGP) { 123203288Srnoland DRM_ERROR("Unknown memory type allocation\n"); 124203288Srnoland return -EINVAL; 125203288Srnoland } 126203288Srnoland if (0 == ((mem->type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized : 127203288Srnoland dev_priv->agp_initialized)) { 128203288Srnoland DRM_ERROR 129203288Srnoland ("Attempt to allocate from uninitialized memory manager.\n"); 130203288Srnoland return -EINVAL; 131203288Srnoland } 132203288Srnoland 133203288Srnoland tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT; 134203288Srnoland item = drm_sman_alloc(&dev_priv->sman, mem->type, tmpSize, 0, 135203288Srnoland (unsigned long)file_priv); 136203288Srnoland if (item) { 137203288Srnoland mem->offset = ((mem->type == VIA_MEM_VIDEO) ? 138203288Srnoland dev_priv->vram_offset : dev_priv->agp_offset) + 139203288Srnoland (item->mm-> 140203288Srnoland offset(item->mm, item->mm_info) << VIA_MM_ALIGN_SHIFT); 141203288Srnoland mem->index = item->user_hash.key; 142203288Srnoland } else { 143203288Srnoland mem->offset = 0; 144203288Srnoland mem->size = 0; 145203288Srnoland mem->index = 0; 146203288Srnoland DRM_DEBUG("Video memory allocation failed\n"); 147203288Srnoland retval = -ENOMEM; 148203288Srnoland } 149203288Srnoland 150203288Srnoland return retval; 151203288Srnoland} 152203288Srnoland 153203288Srnolandint via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) 154203288Srnoland{ 155203288Srnoland drm_via_private_t *dev_priv = dev->dev_private; 156203288Srnoland drm_via_mem_t *mem = data; 157203288Srnoland int ret; 158203288Srnoland 159203288Srnoland ret = drm_sman_free_key(&dev_priv->sman, mem->index); 160203288Srnoland DRM_DEBUG("free = 0x%lx\n", mem->index); 161203288Srnoland 162203288Srnoland return ret; 163203288Srnoland} 164203288Srnoland 165203288Srnoland 166203288Srnolandvoid via_reclaim_buffers_locked(struct drm_device * dev, 167203288Srnoland struct drm_file *file_priv) 168203288Srnoland{ 169203288Srnoland drm_via_private_t *dev_priv = dev->dev_private; 170203288Srnoland 171203288Srnoland if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)file_priv)) 172203288Srnoland return; 173203288Srnoland 174203288Srnoland if (dev->driver->dma_quiescent) 175203288Srnoland dev->driver->dma_quiescent(dev); 176203288Srnoland 177203288Srnoland drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv); 178203288Srnoland 179203288Srnoland return; 180203288Srnoland} 181