xref: /onnv-gate/usr/src/uts/common/io/drm/drm_memory.c (revision 11260:eb8c6f2097e8)
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)&regs, &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