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