1132497Stjr/*- 2132497Stjr * Copyright 2006 Tungsten Graphics Inc., Bismarck, ND., USA. 3132497Stjr * All rights reserved. 4132497Stjr * 5132497Stjr * Permission is hereby granted, free of charge, to any person obtaining a 6132497Stjr * copy of this software and associated documentation files (the "Software"), 7132497Stjr * to deal in the Software without restriction, including without limitation 8132497Stjr * the rights to use, copy, modify, merge, publish, distribute, sub license, 9132497Stjr * and/or sell copies of the Software, and to permit persons to whom the 10132497Stjr * Software is furnished to do so, subject to the following conditions: 11132497Stjr * 12132497Stjr * The above copyright notice and this permission notice (including the 13132497Stjr * next paragraph) shall be included in all copies or substantial portions 14132497Stjr * of the Software. 15132497Stjr * 16132497Stjr * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17132497Stjr * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18132497Stjr * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19132497Stjr * THE AUTHORS OR COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20132497Stjr * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21132497Stjr * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22132497Stjr * DEALINGS IN THE SOFTWARE. 23132497Stjr */ 24132497Stjr 25132497Stjr/* 26132497Stjr * Authors: Thomas Hellstr��m <thomas-at-tungstengraphics-dot-com> 27132497Stjr */ 28132497Stjr 29132497Stjr#include <sys/cdefs.h> 30132497Stjr__FBSDID("$FreeBSD$"); 31132497Stjr 32132497Stjr#include "dev/drm/drmP.h" 33132497Stjr#include "dev/drm/via_drm.h" 34132497Stjr#include "dev/drm/via_drv.h" 35132497Stjr#include "dev/drm/drm_sman.h" 36132497Stjr 37132497Stjr#define VIA_MM_ALIGN_SHIFT 4 38132497Stjr#define VIA_MM_ALIGN_MASK ( (1 << VIA_MM_ALIGN_SHIFT) - 1) 39132497Stjr 40132497Stjrint via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv) 41132497Stjr{ 42132497Stjr drm_via_agp_t *agp = data; 43132497Stjr drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 44132497Stjr int ret; 45132497Stjr 46132497Stjr ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_AGP, 0, 47132497Stjr agp->size >> VIA_MM_ALIGN_SHIFT); 48132497Stjr if (ret) { 49132497Stjr DRM_ERROR("AGP memory manager initialisation error\n"); 50132497Stjr return ret; 51132497Stjr } 52132497Stjr 53132497Stjr dev_priv->agp_initialized = 1; 54132497Stjr dev_priv->agp_offset = agp->offset; 55132497Stjr 56132497Stjr DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size); 57132497Stjr return 0; 58132497Stjr} 59132497Stjr 60132497Stjrint via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv) 61132497Stjr{ 62132497Stjr drm_via_fb_t *fb = data; 63132497Stjr drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 64132497Stjr int ret; 65132497Stjr 66132497Stjr ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_VIDEO, 0, 67132497Stjr fb->size >> VIA_MM_ALIGN_SHIFT); 68132497Stjr if (ret) { 69132497Stjr DRM_ERROR("VRAM memory manager initialisation error\n"); 70132497Stjr return ret; 71132497Stjr } 72132497Stjr 73132497Stjr dev_priv->vram_initialized = 1; 74132497Stjr dev_priv->vram_offset = fb->offset; 75132497Stjr 76132497Stjr DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size); 77132497Stjr 78132497Stjr return 0; 79132497Stjr 80132497Stjr} 81132497Stjr 82132497Stjrint via_final_context(struct drm_device *dev, int context) 83132497Stjr{ 84132497Stjr drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 85132497Stjr 86132497Stjr via_release_futex(dev_priv, context); 87132497Stjr 88132497Stjr#ifdef __linux__ 89132497Stjr /* Linux specific until context tracking code gets ported to BSD */ 90132497Stjr /* Last context, perform cleanup */ 91132497Stjr if (dev->ctx_count == 1 && dev->dev_private) { 92132497Stjr DRM_DEBUG("Last Context\n"); 93132497Stjr drm_irq_uninstall(dev); 94132497Stjr via_cleanup_futex(dev_priv); 95132497Stjr via_do_cleanup_map(dev); 96132497Stjr } 97132497Stjr#endif 98132497Stjr return 1; 99132497Stjr} 100132497Stjr 101132497Stjrvoid via_lastclose(struct drm_device *dev) 102132497Stjr{ 103132497Stjr drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 104132497Stjr 105132497Stjr if (!dev_priv) 106132497Stjr return; 107132497Stjr 108132497Stjr drm_sman_cleanup(&dev_priv->sman); 109132497Stjr dev_priv->vram_initialized = 0; 110132497Stjr dev_priv->agp_initialized = 0; 111132497Stjr} 112 113int via_mem_alloc(struct drm_device *dev, void *data, 114 struct drm_file *file_priv) 115{ 116 drm_via_mem_t *mem = data; 117 int retval = 0; 118 struct drm_memblock_item *item; 119 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 120 unsigned long tmpSize; 121 122 if (mem->type > VIA_MEM_AGP) { 123 DRM_ERROR("Unknown memory type allocation\n"); 124 return -EINVAL; 125 } 126 if (0 == ((mem->type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized : 127 dev_priv->agp_initialized)) { 128 DRM_ERROR 129 ("Attempt to allocate from uninitialized memory manager.\n"); 130 return -EINVAL; 131 } 132 133 tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT; 134 item = drm_sman_alloc(&dev_priv->sman, mem->type, tmpSize, 0, 135 (unsigned long)file_priv); 136 if (item) { 137 mem->offset = ((mem->type == VIA_MEM_VIDEO) ? 138 dev_priv->vram_offset : dev_priv->agp_offset) + 139 (item->mm-> 140 offset(item->mm, item->mm_info) << VIA_MM_ALIGN_SHIFT); 141 mem->index = item->user_hash.key; 142 } else { 143 mem->offset = 0; 144 mem->size = 0; 145 mem->index = 0; 146 DRM_DEBUG("Video memory allocation failed\n"); 147 retval = -ENOMEM; 148 } 149 150 return retval; 151} 152 153int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) 154{ 155 drm_via_private_t *dev_priv = dev->dev_private; 156 drm_via_mem_t *mem = data; 157 int ret; 158 159 ret = drm_sman_free_key(&dev_priv->sman, mem->index); 160 DRM_DEBUG("free = 0x%lx\n", mem->index); 161 162 return ret; 163} 164 165 166void via_reclaim_buffers_locked(struct drm_device * dev, 167 struct drm_file *file_priv) 168{ 169 drm_via_private_t *dev_priv = dev->dev_private; 170 171 if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)file_priv)) 172 return; 173 174 if (dev->driver->dma_quiescent) 175 dev->driver->dma_quiescent(dev); 176 177 drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv); 178 179 return; 180} 181