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 */ 44 typedef 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 52 void 53 drm_mem_init(void) 54 { 55 } 56 57 void 58 drm_mem_uninit(void) 59 { 60 } 61 62 /*ARGSUSED*/ 63 void * 64 drm_alloc(size_t size, int area) 65 { 66 return (kmem_zalloc(1 * size, KM_NOSLEEP)); 67 } 68 69 /*ARGSUSED*/ 70 void * 71 drm_calloc(size_t nmemb, size_t size, int area) 72 { 73 return (kmem_zalloc(size * nmemb, KM_NOSLEEP)); 74 } 75 76 /*ARGSUSED*/ 77 void * 78 drm_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*/ 95 void 96 drm_free(void *pt, size_t size, int area) 97 { 98 kmem_free(pt, size); 99 } 100 101 /*ARGSUSED*/ 102 int 103 drm_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); 140 error: 141 kmem_free(regs, (size_t)length); 142 return (-1); 143 } 144 145 /* data access attributes structure for register access */ 146 static ddi_device_acc_attr_t dev_attr = { 147 DDI_DEVICE_ATTR_V0, 148 DDI_NEVERSWAP_ACC, 149 DDI_STRICTORDER_ACC, 150 }; 151 152 int 153 do_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 182 int 183 drm_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 213 void 214 drm_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 }