1/* 2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6/* 7 * drm_memory.h -- Memory management wrappers for DRM -*- linux-c -*- 8 * Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com 9 */ 10/* 11 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 12 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 13 * Copyright (c) 2009, Intel Corporation. 14 * All Rights Reserved. 15 * 16 * Permission is hereby granted, free of charge, to any person obtaining a 17 * copy of this software and associated documentation files (the "Software"), 18 * to deal in the Software without restriction, including without limitation 19 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 20 * and/or sell copies of the Software, and to permit persons to whom the 21 * Software is furnished to do so, subject to the following conditions: 22 * 23 * The above copyright notice and this permission notice (including the next 24 * paragraph) shall be included in all copies or substantial portions of the 25 * Software. 26 * 27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 30 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 33 * OTHER DEALINGS IN THE SOFTWARE. 34 * 35 * Authors: 36 * Rickard E. (Rik) Faith <faith@valinux.com> 37 * Gareth Hughes <gareth@valinux.com> 38 * 39 */ 40 41#include "drmP.h" 42 43/* Device memory access structure */ 44typedef struct drm_device_iomap { 45 uint_t physical; /* physical address */ 46 uint_t size; /* size of mapping */ 47 uint_t drm_regnum; /* register number */ 48 caddr_t drm_base; /* kernel virtual address */ 49 ddi_acc_handle_t drm_handle; /* data access handle */ 50} drm_device_iomap_t; 51 52void 53drm_mem_init(void) 54{ 55} 56 57void 58drm_mem_uninit(void) 59{ 60} 61 62/*ARGSUSED*/ 63void * 64drm_alloc(size_t size, int area) 65{ 66 return (kmem_zalloc(1 * size, KM_NOSLEEP)); 67} 68 69/*ARGSUSED*/ 70void * 71drm_calloc(size_t nmemb, size_t size, int area) 72{ 73 return (kmem_zalloc(size * nmemb, KM_NOSLEEP)); 74} 75 76/*ARGSUSED*/ 77void * 78drm_realloc(void *oldpt, size_t oldsize, size_t size, int area) 79{ 80 void *pt; 81 82 pt = kmem_zalloc(1 * size, KM_NOSLEEP); 83 if (pt == NULL) { 84 DRM_ERROR("pt is NULL strange"); 85 return (NULL); 86 } 87 if (oldpt && oldsize) { 88 bcopy(pt, oldpt, oldsize); 89 kmem_free(oldpt, oldsize); 90 } 91 return (pt); 92} 93 94/*ARGSUSED*/ 95void 96drm_free(void *pt, size_t size, int area) 97{ 98 kmem_free(pt, size); 99} 100 101/*ARGSUSED*/ 102int 103drm_get_pci_index_reg(dev_info_t *devi, uint_t physical, uint_t size, 104 off_t *off) 105{ 106 int length; 107 pci_regspec_t *regs; 108 int n_reg, i; 109 int regnum; 110 uint_t base, regsize; 111 112 regnum = -1; 113 114 if (ddi_dev_nregs(devi, &n_reg) == DDI_FAILURE) { 115 DRM_ERROR("drm_get_pci_index_reg:ddi_dev_nregs failed\n"); 116 n_reg = 0; 117 return (-1); 118 } 119 120 if (ddi_getlongprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, 121 "assigned-addresses", (caddr_t)®s, &length) != 122 DDI_PROP_SUCCESS) { 123 DRM_ERROR("drm_get_pci_index_reg: ddi_getlongprop failed!\n"); 124 goto error; 125 } 126 127 for (i = 0; i < n_reg; i ++) { 128 base = (uint_t)regs[i].pci_phys_low; 129 regsize = (uint_t)regs[i].pci_size_low; 130 if ((uint_t)physical >= base && 131 (uint_t)physical < (base + regsize)) { 132 regnum = i + 1; 133 *off = (off_t)(physical - base); 134 break; 135 } 136 } 137 138 kmem_free(regs, (size_t)length); 139 return (regnum); 140error: 141 kmem_free(regs, (size_t)length); 142 return (-1); 143} 144 145/* data access attributes structure for register access */ 146static ddi_device_acc_attr_t dev_attr = { 147 DDI_DEVICE_ATTR_V0, 148 DDI_NEVERSWAP_ACC, 149 DDI_STRICTORDER_ACC, 150}; 151 152int 153do_ioremap(dev_info_t *devi, drm_device_iomap_t *iomap) 154{ 155 int regnum; 156 off_t offset; 157 int ret; 158 159 regnum = drm_get_pci_index_reg(devi, iomap->physical, 160 iomap->size, &offset); 161 if (regnum < 0) { 162 DRM_ERROR("do_ioremap: can not find regster entry," 163 " start=0x%x, size=0x%x", iomap->physical, iomap->size); 164 return (ENXIO); 165 } 166 167 iomap->drm_regnum = regnum; 168 169 ret = ddi_regs_map_setup(devi, iomap->drm_regnum, 170 (caddr_t *)&(iomap->drm_base), (offset_t)offset, 171 (offset_t)iomap->size, &dev_attr, &iomap->drm_handle); 172 if (ret < 0) { 173 DRM_ERROR("do_ioremap: failed to map regs: regno=%d," 174 " offset=0x%x", regnum, offset); 175 iomap->drm_handle = NULL; 176 return (EFAULT); 177 } 178 179 return (0); 180} 181 182int 183drm_ioremap(drm_device_t *softstate, drm_local_map_t *map) 184{ 185 drm_device_iomap_t iomap; 186 int ret; 187 188 DRM_DEBUG("drm_ioremap called\n"); 189 190 bzero(&iomap, sizeof (drm_device_iomap_t)); 191 iomap.physical = map->offset; 192 iomap.size = map->size; 193 ret = do_ioremap(softstate->dip, &iomap); 194 195 if (ret) { 196 DRM_ERROR("drm_ioremap: failed, physaddr=0x%x, size=0x%x", 197 map->offset, map->size); 198 return (ret); 199 } 200 201 /* ddi_acc_handle_t */ 202 map->dev_handle = iomap.drm_handle; 203 map->handle = (void *)iomap.drm_base; 204 map->dev_addr = iomap.drm_base; 205 206 DRM_DEBUG( 207 "map->handle is %p map->dev_addr is %lx map->size %x", 208 (void *)map->handle, (unsigned long)map->dev_addr, map->size); 209 210 return (0); 211} 212 213void 214drm_ioremapfree(drm_local_map_t *map) 215{ 216 if (map->dev_handle == NULL) { 217 DRM_ERROR("drm_ioremapfree: handle is NULL"); 218 return; 219 } 220 ddi_regs_map_free(&map->dev_handle); 221} 222