12820Skz151634 /*
2*11260SMiao.Chen@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
32820Skz151634 * Use is subject to license terms.
42820Skz151634 */
52820Skz151634
62820Skz151634 /*
72820Skz151634 * drm_memory.h -- Memory management wrappers for DRM -*- linux-c -*-
82820Skz151634 * Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com
92820Skz151634 */
102820Skz151634 /*
112820Skz151634 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
122820Skz151634 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
13*11260SMiao.Chen@Sun.COM * Copyright (c) 2009, Intel Corporation.
142820Skz151634 * All Rights Reserved.
152820Skz151634 *
162820Skz151634 * Permission is hereby granted, free of charge, to any person obtaining a
172820Skz151634 * copy of this software and associated documentation files (the "Software"),
182820Skz151634 * to deal in the Software without restriction, including without limitation
192820Skz151634 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
202820Skz151634 * and/or sell copies of the Software, and to permit persons to whom the
212820Skz151634 * Software is furnished to do so, subject to the following conditions:
222820Skz151634 *
232820Skz151634 * The above copyright notice and this permission notice (including the next
242820Skz151634 * paragraph) shall be included in all copies or substantial portions of the
252820Skz151634 * Software.
262820Skz151634 *
272820Skz151634 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
282820Skz151634 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
292820Skz151634 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
302820Skz151634 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
312820Skz151634 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
322820Skz151634 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
332820Skz151634 * OTHER DEALINGS IN THE SOFTWARE.
342820Skz151634 *
352820Skz151634 * Authors:
362820Skz151634 * Rickard E. (Rik) Faith <faith@valinux.com>
372820Skz151634 * Gareth Hughes <gareth@valinux.com>
382820Skz151634 *
392820Skz151634 */
402820Skz151634
412820Skz151634 #include "drmP.h"
422820Skz151634
432820Skz151634 /* Device memory access structure */
442820Skz151634 typedef struct drm_device_iomap {
452820Skz151634 uint_t physical; /* physical address */
462820Skz151634 uint_t size; /* size of mapping */
472820Skz151634 uint_t drm_regnum; /* register number */
482820Skz151634 caddr_t drm_base; /* kernel virtual address */
492820Skz151634 ddi_acc_handle_t drm_handle; /* data access handle */
502820Skz151634 } drm_device_iomap_t;
512820Skz151634
522820Skz151634 void
drm_mem_init(void)532820Skz151634 drm_mem_init(void)
542820Skz151634 {
552820Skz151634 }
562820Skz151634
572820Skz151634 void
drm_mem_uninit(void)582820Skz151634 drm_mem_uninit(void)
592820Skz151634 {
602820Skz151634 }
612820Skz151634
622820Skz151634 /*ARGSUSED*/
632820Skz151634 void *
drm_alloc(size_t size,int area)642820Skz151634 drm_alloc(size_t size, int area)
652820Skz151634 {
662820Skz151634 return (kmem_zalloc(1 * size, KM_NOSLEEP));
672820Skz151634 }
682820Skz151634
692820Skz151634 /*ARGSUSED*/
702820Skz151634 void *
drm_calloc(size_t nmemb,size_t size,int area)712820Skz151634 drm_calloc(size_t nmemb, size_t size, int area)
722820Skz151634 {
732820Skz151634 return (kmem_zalloc(size * nmemb, KM_NOSLEEP));
742820Skz151634 }
752820Skz151634
762820Skz151634 /*ARGSUSED*/
772820Skz151634 void *
drm_realloc(void * oldpt,size_t oldsize,size_t size,int area)782820Skz151634 drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
792820Skz151634 {
802820Skz151634 void *pt;
812820Skz151634
822820Skz151634 pt = kmem_zalloc(1 * size, KM_NOSLEEP);
832820Skz151634 if (pt == NULL) {
842820Skz151634 DRM_ERROR("pt is NULL strange");
852820Skz151634 return (NULL);
862820Skz151634 }
872820Skz151634 if (oldpt && oldsize) {
882820Skz151634 bcopy(pt, oldpt, oldsize);
892820Skz151634 kmem_free(oldpt, oldsize);
902820Skz151634 }
912820Skz151634 return (pt);
922820Skz151634 }
932820Skz151634
942820Skz151634 /*ARGSUSED*/
952820Skz151634 void
drm_free(void * pt,size_t size,int area)962820Skz151634 drm_free(void *pt, size_t size, int area)
972820Skz151634 {
982820Skz151634 kmem_free(pt, size);
992820Skz151634 }
1002820Skz151634
1012820Skz151634 /*ARGSUSED*/
1022820Skz151634 int
drm_get_pci_index_reg(dev_info_t * devi,uint_t physical,uint_t size,off_t * off)1032820Skz151634 drm_get_pci_index_reg(dev_info_t *devi, uint_t physical, uint_t size,
1042820Skz151634 off_t *off)
1052820Skz151634 {
1062820Skz151634 int length;
1072820Skz151634 pci_regspec_t *regs;
1082820Skz151634 int n_reg, i;
1092820Skz151634 int regnum;
1102820Skz151634 uint_t base, regsize;
1112820Skz151634
1122820Skz151634 regnum = -1;
1132820Skz151634
1142820Skz151634 if (ddi_dev_nregs(devi, &n_reg) == DDI_FAILURE) {
1152820Skz151634 DRM_ERROR("drm_get_pci_index_reg:ddi_dev_nregs failed\n");
1162820Skz151634 n_reg = 0;
1172820Skz151634 return (-1);
1182820Skz151634 }
1192820Skz151634
1202820Skz151634 if (ddi_getlongprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
1212820Skz151634 "assigned-addresses", (caddr_t)®s, &length) !=
1222820Skz151634 DDI_PROP_SUCCESS) {
1232820Skz151634 DRM_ERROR("drm_get_pci_index_reg: ddi_getlongprop failed!\n");
1242820Skz151634 goto error;
1252820Skz151634 }
1262820Skz151634
1272820Skz151634 for (i = 0; i < n_reg; i ++) {
1282820Skz151634 base = (uint_t)regs[i].pci_phys_low;
1292820Skz151634 regsize = (uint_t)regs[i].pci_size_low;
1302820Skz151634 if ((uint_t)physical >= base &&
1312820Skz151634 (uint_t)physical < (base + regsize)) {
1325804Scg149915 regnum = i + 1;
1335804Scg149915 *off = (off_t)(physical - base);
1345804Scg149915 break;
1352820Skz151634 }
1362820Skz151634 }
137*11260SMiao.Chen@Sun.COM
1382820Skz151634 kmem_free(regs, (size_t)length);
1392820Skz151634 return (regnum);
1402820Skz151634 error:
1412820Skz151634 kmem_free(regs, (size_t)length);
1422820Skz151634 return (-1);
1432820Skz151634 }
1442820Skz151634
1452820Skz151634 /* data access attributes structure for register access */
1462820Skz151634 static ddi_device_acc_attr_t dev_attr = {
1472820Skz151634 DDI_DEVICE_ATTR_V0,
1482820Skz151634 DDI_NEVERSWAP_ACC,
1492820Skz151634 DDI_STRICTORDER_ACC,
1502820Skz151634 };
1512820Skz151634
1522820Skz151634 int
do_ioremap(dev_info_t * devi,drm_device_iomap_t * iomap)1532820Skz151634 do_ioremap(dev_info_t *devi, drm_device_iomap_t *iomap)
1542820Skz151634 {
1555804Scg149915 int regnum;
1562820Skz151634 off_t offset;
1572820Skz151634 int ret;
1582820Skz151634
1592820Skz151634 regnum = drm_get_pci_index_reg(devi, iomap->physical,
1602820Skz151634 iomap->size, &offset);
1612820Skz151634 if (regnum < 0) {
1625804Scg149915 DRM_ERROR("do_ioremap: can not find regster entry,"
1635804Scg149915 " start=0x%x, size=0x%x", iomap->physical, iomap->size);
1645804Scg149915 return (ENXIO);
1652820Skz151634 }
1662820Skz151634
1672820Skz151634 iomap->drm_regnum = regnum;
1682820Skz151634
1692820Skz151634 ret = ddi_regs_map_setup(devi, iomap->drm_regnum,
1702820Skz151634 (caddr_t *)&(iomap->drm_base), (offset_t)offset,
1712820Skz151634 (offset_t)iomap->size, &dev_attr, &iomap->drm_handle);
1722820Skz151634 if (ret < 0) {
1735804Scg149915 DRM_ERROR("do_ioremap: failed to map regs: regno=%d,"
1745804Scg149915 " offset=0x%x", regnum, offset);
1752820Skz151634 iomap->drm_handle = NULL;
1765804Scg149915 return (EFAULT);
1772820Skz151634 }
1782820Skz151634
1792820Skz151634 return (0);
1802820Skz151634 }
1812820Skz151634
1822820Skz151634 int
drm_ioremap(drm_device_t * softstate,drm_local_map_t * map)1835804Scg149915 drm_ioremap(drm_device_t *softstate, drm_local_map_t *map)
1842820Skz151634 {
1852820Skz151634 drm_device_iomap_t iomap;
1862820Skz151634 int ret;
1872820Skz151634
1882820Skz151634 DRM_DEBUG("drm_ioremap called\n");
1892820Skz151634
1902820Skz151634 bzero(&iomap, sizeof (drm_device_iomap_t));
1915804Scg149915 iomap.physical = map->offset;
1922820Skz151634 iomap.size = map->size;
1932820Skz151634 ret = do_ioremap(softstate->dip, &iomap);
1942820Skz151634
1952820Skz151634 if (ret) {
1965804Scg149915 DRM_ERROR("drm_ioremap: failed, physaddr=0x%x, size=0x%x",
1975804Scg149915 map->offset, map->size);
1985804Scg149915 return (ret);
1992820Skz151634 }
2005804Scg149915
2015804Scg149915 /* ddi_acc_handle_t */
2022820Skz151634 map->dev_handle = iomap.drm_handle;
2035804Scg149915 map->handle = (void *)iomap.drm_base;
2045804Scg149915 map->dev_addr = iomap.drm_base;
2052820Skz151634
2062820Skz151634 DRM_DEBUG(
207*11260SMiao.Chen@Sun.COM "map->handle is %p map->dev_addr is %lx map->size %x",
208*11260SMiao.Chen@Sun.COM (void *)map->handle, (unsigned long)map->dev_addr, map->size);
2092820Skz151634
2105804Scg149915 return (0);
2112820Skz151634 }
2122820Skz151634
2132820Skz151634 void
drm_ioremapfree(drm_local_map_t * map)2142820Skz151634 drm_ioremapfree(drm_local_map_t *map)
2152820Skz151634 {
2162820Skz151634 if (map->dev_handle == NULL) {
2172820Skz151634 DRM_ERROR("drm_ioremapfree: handle is NULL");
2182820Skz151634 return;
2192820Skz151634 }
2202820Skz151634 ddi_regs_map_free(&map->dev_handle);
2212820Skz151634 }
222