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_agpsupport.h -- DRM support for AGP/GART backend -*- linux-c -*-
82820Skz151634 * Created: Mon Dec 13 09:56:45 1999 by faith@precisioninsight.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 * Author:
362820Skz151634 * Rickard E. (Rik) Faith <faith@valinux.com>
372820Skz151634 * Gareth Hughes <gareth@valinux.com>
382820Skz151634 *
392820Skz151634 */
402820Skz151634
412820Skz151634 #include "drm.h"
422820Skz151634 #include "drmP.h"
432820Skz151634
442820Skz151634 #ifndef AGP_PAGE_SIZE
452820Skz151634 #define AGP_PAGE_SIZE 4096
462820Skz151634 #define AGP_PAGE_SHIFT 12
472820Skz151634 #endif
482820Skz151634
495804Scg149915 /*
505804Scg149915 * The agpa_key field of struct agp_allocate_t actually is
515804Scg149915 * an index to an array. It can be zero. But we will use
525804Scg149915 * this agpa_key as a handle returned to userland. Generally,
535804Scg149915 * 0 is not a valid value for a handle, so we add an offset
545804Scg149915 * to the key to get a handle.
555804Scg149915 */
565804Scg149915 #define DRM_AGP_KEY_OFFSET 8
575804Scg149915
585804Scg149915 extern int drm_supp_device_capability(void *handle, int capid);
595804Scg149915
602820Skz151634 /*ARGSUSED*/
612820Skz151634 int
drm_device_is_agp(drm_device_t * dev)625804Scg149915 drm_device_is_agp(drm_device_t *dev)
632820Skz151634 {
645804Scg149915 int ret;
655804Scg149915
665804Scg149915 if (dev->driver->device_is_agp != NULL) {
675804Scg149915 /*
685804Scg149915 * device_is_agp returns a tristate:
695804Scg149915 * 0 = not AGP;
705804Scg149915 * 1 = definitely AGP;
715804Scg149915 * 2 = fall back to PCI capability
725804Scg149915 */
735804Scg149915 ret = (*dev->driver->device_is_agp)(dev);
745804Scg149915 if (ret != DRM_MIGHT_BE_AGP)
755804Scg149915 return (ret);
765804Scg149915 }
775804Scg149915
785804Scg149915 return (drm_supp_device_capability(dev->drm_handle, PCIY_AGP));
795804Scg149915
802820Skz151634 }
812820Skz151634
822820Skz151634 /*ARGSUSED*/
832820Skz151634 int
drm_device_is_pcie(drm_device_t * dev)845804Scg149915 drm_device_is_pcie(drm_device_t *dev)
852820Skz151634 {
865804Scg149915 return (drm_supp_device_capability(dev->drm_handle, PCIY_EXPRESS));
872820Skz151634 }
882820Skz151634
892820Skz151634
902820Skz151634 /*ARGSUSED*/
912820Skz151634 int
drm_agp_info(DRM_IOCTL_ARGS)922820Skz151634 drm_agp_info(DRM_IOCTL_ARGS)
932820Skz151634 {
942820Skz151634 DRM_DEVICE;
955804Scg149915 agp_info_t *agpinfo;
965804Scg149915 drm_agp_info_t info;
972820Skz151634
982820Skz151634 if (!dev->agp || !dev->agp->acquired)
995804Scg149915 return (EINVAL);
1002820Skz151634
1015804Scg149915 agpinfo = &dev->agp->agp_info;
1025804Scg149915 info.agp_version_major = agpinfo->agpi_version.agpv_major;
1035804Scg149915 info.agp_version_minor = agpinfo->agpi_version.agpv_minor;
1045804Scg149915 info.mode = agpinfo->agpi_mode;
1055804Scg149915 info.aperture_base = agpinfo->agpi_aperbase;
1065804Scg149915 info.aperture_size = agpinfo->agpi_apersize* 1024 * 1024;
1075804Scg149915 info.memory_allowed = agpinfo->agpi_pgtotal << PAGE_SHIFT;
1085804Scg149915 info.memory_used = agpinfo->agpi_pgused << PAGE_SHIFT;
1095804Scg149915 info.id_vendor = agpinfo->agpi_devid & 0xffff;
1105804Scg149915 info.id_device = agpinfo->agpi_devid >> 16;
1115804Scg149915
1125804Scg149915 DRM_COPYTO_WITH_RETURN((void *)data, &info, sizeof (info));
1132820Skz151634 return (0);
1142820Skz151634 }
1152820Skz151634
1162820Skz151634 /*ARGSUSED*/
1172820Skz151634 int
drm_agp_acquire(DRM_IOCTL_ARGS)1182820Skz151634 drm_agp_acquire(DRM_IOCTL_ARGS)
1192820Skz151634 {
1202820Skz151634 DRM_DEVICE;
1212820Skz151634 int ret, rval;
1222820Skz151634
1232820Skz151634 if (!dev->agp) {
1245804Scg149915 DRM_ERROR("drm_agp_acquire : agp isn't initialized yet");
1255804Scg149915 return (ENODEV);
1262820Skz151634 }
1275804Scg149915 ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_ACQUIRE,
1282820Skz151634 (uintptr_t)0, FKIOCTL, kcred, &rval);
1292820Skz151634 if (ret) {
1302820Skz151634 DRM_ERROR("drm_agp_acquired: AGPIOC_ACQUIRE failed\n");
1315804Scg149915 return (EIO);
1322820Skz151634 }
1332820Skz151634 dev->agp->acquired = 1;
1342820Skz151634
1352820Skz151634 return (0);
1362820Skz151634 }
1372820Skz151634
1382820Skz151634 /*ARGSUSED*/
1392820Skz151634 int
drm_agp_release(DRM_IOCTL_ARGS)1402820Skz151634 drm_agp_release(DRM_IOCTL_ARGS)
1412820Skz151634 {
1422820Skz151634 DRM_DEVICE;
1432820Skz151634 int ret, rval;
1442820Skz151634
1452820Skz151634 if (!dev->agp)
1465804Scg149915 return (ENODEV);
1472820Skz151634 if (!dev->agp->acquired)
1485804Scg149915 return (EBUSY);
1492820Skz151634
1505804Scg149915 ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_RELEASE,
1515804Scg149915 (intptr_t)0, FKIOCTL, kcred, &rval);
1525804Scg149915 if (ret) {
1535804Scg149915 DRM_ERROR("drm_agp_release: AGPIOC_RELEASE failed\n");
1545804Scg149915 return (ENXIO);
1552820Skz151634 }
1562820Skz151634 dev->agp->acquired = 0;
1572820Skz151634
1585804Scg149915 return (ret);
1595804Scg149915 }
1605804Scg149915
1615804Scg149915
1625804Scg149915 int
drm_agp_do_release(drm_device_t * dev)1635804Scg149915 drm_agp_do_release(drm_device_t *dev)
1645804Scg149915 {
1655804Scg149915 int ret, rval;
1665804Scg149915
1675804Scg149915 ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_RELEASE,
1685804Scg149915 (intptr_t)0, FKIOCTL, kcred, &rval);
1695804Scg149915
1705804Scg149915 if (ret == 0)
1715804Scg149915 dev->agp->acquired = 0;
1725804Scg149915
1735804Scg149915 return (ret);
1742820Skz151634 }
1752820Skz151634
1762820Skz151634 /*ARGSUSED*/
1772820Skz151634 int
drm_agp_enable(DRM_IOCTL_ARGS)1782820Skz151634 drm_agp_enable(DRM_IOCTL_ARGS)
1792820Skz151634 {
1802820Skz151634 DRM_DEVICE;
1812820Skz151634 drm_agp_mode_t modes;
1822820Skz151634 agp_setup_t setup;
1832820Skz151634 int ret, rval;
1842820Skz151634
1852820Skz151634 if (!dev->agp)
1865804Scg149915 return (ENODEV);
1872820Skz151634 if (!dev->agp->acquired)
1885804Scg149915 return (EBUSY);
1892820Skz151634
1905804Scg149915 DRM_COPYFROM_WITH_RETURN(&modes, (void *)data, sizeof (modes));
1912820Skz151634
1922820Skz151634 dev->agp->mode = modes.mode;
1935804Scg149915 setup.agps_mode = (uint32_t)modes.mode;
1942820Skz151634
195*11260SMiao.Chen@Sun.COM
1962820Skz151634 DRM_DEBUG("drm_agp_enable: dev->agp->mode=%lx", modes.mode);
1972820Skz151634
1985804Scg149915 ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_SETUP,
1995804Scg149915 (intptr_t)&setup, FKIOCTL, kcred, &rval);
2002820Skz151634 if (ret) {
2015804Scg149915 DRM_ERROR("drm_agp_enable: failed");
2025804Scg149915 return (EIO);
2032820Skz151634 }
2042820Skz151634
2052820Skz151634 dev->agp->base = dev->agp->agp_info.agpi_aperbase;
2062820Skz151634 dev->agp->enabled = 1;
2072820Skz151634
208*11260SMiao.Chen@Sun.COM DRM_DEBUG("drm_agp_enable: dev->agp->base=0x%lx", dev->agp->base);
2092820Skz151634 return (0);
2102820Skz151634 }
2112820Skz151634
2122820Skz151634 /*ARGSUSED*/
2132820Skz151634 int
drm_agp_alloc(DRM_IOCTL_ARGS)2142820Skz151634 drm_agp_alloc(DRM_IOCTL_ARGS)
2152820Skz151634 {
2162820Skz151634 DRM_DEVICE;
2172820Skz151634 drm_agp_mem_t *entry;
2182820Skz151634 agp_allocate_t alloc;
2192820Skz151634 drm_agp_buffer_t request;
2202820Skz151634 int pages;
2212820Skz151634 int ret, rval;
2222820Skz151634
2232820Skz151634 if (!dev->agp || !dev->agp->acquired)
2245804Scg149915 return (EINVAL);
2252820Skz151634
2265804Scg149915 DRM_COPYFROM_WITH_RETURN(&request, (void *)data, sizeof (request));
2272820Skz151634
2285804Scg149915 entry = kmem_zalloc(sizeof (*entry), KM_SLEEP);
2295804Scg149915
2302820Skz151634 pages = btopr(request.size);
2312820Skz151634 alloc.agpa_pgcount = pages;
2325804Scg149915 alloc.agpa_type = AGP_NORMAL;
2335804Scg149915 ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_ALLOCATE,
2345804Scg149915 (intptr_t)&alloc, FKIOCTL, kcred, &rval);
2352820Skz151634 if (ret) {
2365804Scg149915 DRM_ERROR("drm_agp_alloc: AGPIOC_ALLOCATE failed, ret=%d", ret);
2375804Scg149915 kmem_free(entry, sizeof (*entry));
2385804Scg149915 return (ret);
2392820Skz151634 }
2402820Skz151634
2412820Skz151634 entry->bound = 0;
2422820Skz151634 entry->pages = pages;
2435804Scg149915 entry->handle = (void*)(uintptr_t)(alloc.agpa_key + DRM_AGP_KEY_OFFSET);
2442820Skz151634 entry->prev = NULL;
2455804Scg149915 entry->phys_addr = (void*)(uintptr_t)alloc.agpa_physical;
2462820Skz151634 entry->next = dev->agp->memory;
2472820Skz151634 if (dev->agp->memory)
2485804Scg149915 dev->agp->memory->prev = entry;
2492820Skz151634 dev->agp->memory = entry;
2502820Skz151634
251*11260SMiao.Chen@Sun.COM DRM_DEBUG("entry->phys_addr %lx", entry->phys_addr);
252*11260SMiao.Chen@Sun.COM
2535804Scg149915 /* physical is used only by i810 driver */
2542820Skz151634 request.physical = alloc.agpa_physical;
2555804Scg149915 request.handle = (unsigned long)entry->handle;
2562820Skz151634
2575804Scg149915 /*
2585804Scg149915 * If failed to ddi_copyout(), we will free allocated AGP memory
2595804Scg149915 * when closing drm
2605804Scg149915 */
2615804Scg149915 DRM_COPYTO_WITH_RETURN((void *)data, &request, sizeof (request));
2622820Skz151634
2632820Skz151634 return (0);
2642820Skz151634 }
2652820Skz151634
2662820Skz151634 /*ARGSUSED*/
2672820Skz151634 static drm_agp_mem_t *
drm_agp_lookup_entry(drm_device_t * dev,void * handle)2685804Scg149915 drm_agp_lookup_entry(drm_device_t *dev, void *handle)
2692820Skz151634 {
2702820Skz151634 drm_agp_mem_t *entry;
2712820Skz151634
2722820Skz151634 for (entry = dev->agp->memory; entry; entry = entry->next) {
2732820Skz151634 if (entry->handle == handle)
2742820Skz151634 return (entry);
2752820Skz151634 }
2762820Skz151634
2772820Skz151634 return (NULL);
2782820Skz151634 }
2792820Skz151634
2802820Skz151634 /*ARGSUSED*/
2812820Skz151634 int
drm_agp_unbind(DRM_IOCTL_ARGS)2822820Skz151634 drm_agp_unbind(DRM_IOCTL_ARGS)
2832820Skz151634 {
2842820Skz151634 DRM_DEVICE;
2852820Skz151634 agp_unbind_t unbind;
2862820Skz151634 drm_agp_binding_t request;
2872820Skz151634 drm_agp_mem_t *entry;
2882820Skz151634 int ret, rval;
2892820Skz151634
2902820Skz151634 if (!dev->agp || !dev->agp->acquired)
2915804Scg149915 return (EINVAL);
2925804Scg149915
2935804Scg149915 DRM_COPYFROM_WITH_RETURN(&request, (void *)data, sizeof (request));
2942820Skz151634
2952820Skz151634 if (!(entry = drm_agp_lookup_entry(dev, (void *)request.handle)))
2965804Scg149915 return (EINVAL);
2972820Skz151634 if (!entry->bound)
2985804Scg149915 return (EINVAL);
2992820Skz151634
3002820Skz151634 unbind.agpu_pri = 0;
3015804Scg149915 unbind.agpu_key = (uintptr_t)entry->handle - DRM_AGP_KEY_OFFSET;
3022820Skz151634
3035804Scg149915 ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_UNBIND,
3042820Skz151634 (intptr_t)&unbind, FKIOCTL, kcred, &rval);
3052820Skz151634 if (ret) {
3062820Skz151634 DRM_ERROR("drm_agp_unbind: AGPIOC_UNBIND failed");
3075804Scg149915 return (EIO);
3082820Skz151634 }
3092820Skz151634 entry->bound = 0;
3102820Skz151634 return (0);
3112820Skz151634 }
3122820Skz151634
3132820Skz151634 /*ARGSUSED*/
3142820Skz151634 int
drm_agp_bind(DRM_IOCTL_ARGS)3152820Skz151634 drm_agp_bind(DRM_IOCTL_ARGS)
3162820Skz151634 {
3172820Skz151634 DRM_DEVICE;
3182820Skz151634 drm_agp_binding_t request;
3192820Skz151634 drm_agp_mem_t *entry;
3205804Scg149915 int start;
3215804Scg149915 uint_t key;
3222820Skz151634
3232820Skz151634 if (!dev->agp || !dev->agp->acquired)
3245804Scg149915 return (EINVAL);
3255804Scg149915
3265804Scg149915 DRM_COPYFROM_WITH_RETURN(&request, (void *)data, sizeof (request));
3275804Scg149915
3285804Scg149915 entry = drm_agp_lookup_entry(dev, (void *)request.handle);
3295804Scg149915 if (!entry || entry->bound)
3305804Scg149915 return (EINVAL);
3312820Skz151634
3325804Scg149915 key = (uintptr_t)entry->handle - DRM_AGP_KEY_OFFSET;
3335804Scg149915 start = btopr(request.offset);
3345804Scg149915 if (drm_agp_bind_memory(key, start, dev)) {
3355804Scg149915 DRM_ERROR("drm_agp_bind: failed key=%x, start=0x%x, "
3365804Scg149915 "agp_base=0x%lx", key, start, dev->agp->base);
3375804Scg149915 return (EIO);
3385804Scg149915 }
3392820Skz151634
3405804Scg149915 entry->bound = dev->agp->base + (start << AGP_PAGE_SHIFT);
3412820Skz151634
3422820Skz151634 return (0);
3432820Skz151634 }
3442820Skz151634
3452820Skz151634 /*ARGSUSED*/
3462820Skz151634 int
drm_agp_free(DRM_IOCTL_ARGS)3472820Skz151634 drm_agp_free(DRM_IOCTL_ARGS)
3482820Skz151634 {
3492820Skz151634 DRM_DEVICE;
3502820Skz151634 drm_agp_buffer_t request;
3512820Skz151634 drm_agp_mem_t *entry;
3522820Skz151634 int ret, rval;
3535804Scg149915 int agpu_key;
3542820Skz151634
3555804Scg149915 DRM_COPYFROM_WITH_RETURN(&request, (void *)data, sizeof (request));
3562820Skz151634 if (!dev->agp || !dev->agp->acquired)
3575804Scg149915 return (EINVAL);
3582820Skz151634 if (!(entry = drm_agp_lookup_entry(dev, (void *)request.handle)))
3595804Scg149915 return (EINVAL);
3602820Skz151634 if (entry->bound)
3615804Scg149915 (void) drm_agp_unbind_memory(request.handle, dev);
3622820Skz151634
3635804Scg149915 if (entry == dev->agp->memory)
3645804Scg149915 dev->agp->memory = entry->next;
3652820Skz151634 if (entry->prev)
3662820Skz151634 entry->prev->next = entry->next;
3672820Skz151634 if (entry->next)
3682820Skz151634 entry->next->prev = entry->prev;
3692820Skz151634
3705804Scg149915 agpu_key = (uintptr_t)entry->handle - DRM_AGP_KEY_OFFSET;
3715804Scg149915 ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_DEALLOCATE,
3725804Scg149915 (intptr_t)agpu_key, FKIOCTL, kcred, &rval);
3735804Scg149915 if (ret) {
3745804Scg149915 DRM_ERROR("drm_agp_free: AGPIOC_DEALLOCATE failed,"
3755804Scg149915 "akey=%d, ret=%d", agpu_key, ret);
3765804Scg149915 return (EIO);
3775804Scg149915 }
3782820Skz151634 drm_free(entry, sizeof (*entry), DRM_MEM_AGPLISTS);
3792820Skz151634 return (0);
3802820Skz151634 }
3812820Skz151634
3822820Skz151634 /*ARGSUSED*/
3832820Skz151634 drm_agp_head_t *
drm_agp_init(drm_device_t * dev)3845804Scg149915 drm_agp_init(drm_device_t *dev)
3852820Skz151634 {
3865804Scg149915 drm_agp_head_t *agp = NULL;
3875804Scg149915 int retval, rval;
3882820Skz151634
3895804Scg149915 agp = kmem_zalloc(sizeof (drm_agp_head_t), KM_SLEEP);
3905804Scg149915
3915804Scg149915 retval = ldi_ident_from_dip(dev->dip, &agp->agpgart_li);
3925804Scg149915 if (retval != 0) {
3935804Scg149915 DRM_ERROR("drm_agp_init: failed to get layerd ident, retval=%d",
3945804Scg149915 retval);
3955804Scg149915 goto err_1;
3965804Scg149915 }
3975804Scg149915
3985804Scg149915 retval = ldi_open_by_name(AGP_DEVICE, FEXCL, kcred,
3995804Scg149915 &agp->agpgart_lh, agp->agpgart_li);
4005804Scg149915 if (retval != 0) {
4015804Scg149915 DRM_ERROR("drm_agp_init: failed to open %s, retval=%d",
4025804Scg149915 AGP_DEVICE, retval);
4035804Scg149915 goto err_2;
4045804Scg149915 }
4055804Scg149915
4065804Scg149915 retval = ldi_ioctl(agp->agpgart_lh, AGPIOC_INFO,
4075804Scg149915 (intptr_t)&agp->agp_info, FKIOCTL, kcred, &rval);
4085804Scg149915
4095804Scg149915 if (retval != 0) {
4105804Scg149915 DRM_ERROR("drm_agp_init: failed to get agpinfo, retval=%d",
4115804Scg149915 retval);
4125804Scg149915 goto err_3;
4135804Scg149915 }
4145804Scg149915
4155804Scg149915 return (agp);
4165804Scg149915
4175804Scg149915 err_3:
4185804Scg149915 (void) ldi_close(agp->agpgart_lh, FEXCL, kcred);
4195804Scg149915
4205804Scg149915 err_2:
4215804Scg149915 ldi_ident_release(agp->agpgart_li);
4225804Scg149915
4235804Scg149915 err_1:
4245804Scg149915 kmem_free(agp, sizeof (drm_agp_head_t));
4252820Skz151634 return (NULL);
4262820Skz151634 }
4272820Skz151634
4282820Skz151634 /*ARGSUSED*/
4292820Skz151634 void
drm_agp_fini(drm_device_t * dev)4305804Scg149915 drm_agp_fini(drm_device_t *dev)
4312820Skz151634 {
4325804Scg149915 drm_agp_head_t *agp = dev->agp;
4335804Scg149915 (void) ldi_close(agp->agpgart_lh, FEXCL, kcred);
4345804Scg149915 ldi_ident_release(agp->agpgart_li);
4355804Scg149915 kmem_free(agp, sizeof (drm_agp_head_t));
4365804Scg149915 dev->agp = NULL;
4372820Skz151634 }
4382820Skz151634
4392820Skz151634
4402820Skz151634 /*ARGSUSED*/
4412820Skz151634 void *
drm_agp_allocate_memory(size_t pages,uint32_t type,drm_device_t * dev)442*11260SMiao.Chen@Sun.COM drm_agp_allocate_memory(size_t pages, uint32_t type, drm_device_t *dev)
4432820Skz151634 {
4442820Skz151634 return (NULL);
4452820Skz151634 }
4462820Skz151634
4472820Skz151634 /*ARGSUSED*/
4482820Skz151634 int
drm_agp_free_memory(agp_allocate_t * handle,drm_device_t * dev)449*11260SMiao.Chen@Sun.COM drm_agp_free_memory(agp_allocate_t *handle, drm_device_t *dev)
4502820Skz151634 {
4512820Skz151634 return (1);
4522820Skz151634 }
4532820Skz151634
4542820Skz151634 /*ARGSUSED*/
4552820Skz151634 int
drm_agp_bind_memory(unsigned int key,uint32_t start,drm_device_t * dev)4562820Skz151634 drm_agp_bind_memory(unsigned int key, uint32_t start, drm_device_t *dev)
4572820Skz151634 {
4582820Skz151634 agp_bind_t bind;
4592820Skz151634 int ret, rval;
4602820Skz151634
4612820Skz151634 bind.agpb_pgstart = start;
4622820Skz151634 bind.agpb_key = key;
4635804Scg149915 ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_BIND,
4642820Skz151634 (intptr_t)&bind, FKIOCTL, kcred, &rval);
4652820Skz151634 if (ret) {
4662820Skz151634 DRM_DEBUG("drm_agp_bind_meory: AGPIOC_BIND failed");
4675804Scg149915 return (EIO);
4682820Skz151634 }
4692820Skz151634 return (0);
4702820Skz151634 }
4712820Skz151634
4722820Skz151634 /*ARGSUSED*/
4732820Skz151634 int
drm_agp_unbind_memory(unsigned long handle,drm_device_t * dev)4745804Scg149915 drm_agp_unbind_memory(unsigned long handle, drm_device_t *dev)
4752820Skz151634 {
4762820Skz151634 agp_unbind_t unbind;
4772820Skz151634 drm_agp_mem_t *entry;
4782820Skz151634 int ret, rval;
4792820Skz151634
4802820Skz151634 if (!dev->agp || !dev->agp->acquired)
4815804Scg149915 return (EINVAL);
4822820Skz151634
4835804Scg149915 entry = drm_agp_lookup_entry(dev, (void *)handle);
4845804Scg149915 if (!entry || !entry->bound)
4855804Scg149915 return (EINVAL);
4862820Skz151634
4872820Skz151634 unbind.agpu_pri = 0;
4885804Scg149915 unbind.agpu_key = (uintptr_t)entry->handle - DRM_AGP_KEY_OFFSET;
4892820Skz151634
4905804Scg149915 ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_UNBIND,
4915804Scg149915 (intptr_t)&unbind, FKIOCTL, kcred, &rval);
4922820Skz151634 if (ret) {
4932820Skz151634 DRM_ERROR("drm_agp_unbind: AGPIO_UNBIND failed");
4945804Scg149915 return (EIO);
4952820Skz151634 }
4962820Skz151634 entry->bound = 0;
4972820Skz151634 return (0);
4982820Skz151634 }
499*11260SMiao.Chen@Sun.COM
500*11260SMiao.Chen@Sun.COM /*
501*11260SMiao.Chen@Sun.COM * Binds a collection of pages into AGP memory at the given offset, returning
502*11260SMiao.Chen@Sun.COM * the AGP memory structure containing them.
503*11260SMiao.Chen@Sun.COM *
504*11260SMiao.Chen@Sun.COM * No reference is held on the pages during this time -- it is up to the
505*11260SMiao.Chen@Sun.COM * caller to handle that.
506*11260SMiao.Chen@Sun.COM */
507*11260SMiao.Chen@Sun.COM int
drm_agp_bind_pages(drm_device_t * dev,pfn_t * pages,unsigned long num_pages,uint32_t gtt_offset)508*11260SMiao.Chen@Sun.COM drm_agp_bind_pages(drm_device_t *dev,
509*11260SMiao.Chen@Sun.COM pfn_t *pages,
510*11260SMiao.Chen@Sun.COM unsigned long num_pages,
511*11260SMiao.Chen@Sun.COM uint32_t gtt_offset)
512*11260SMiao.Chen@Sun.COM {
513*11260SMiao.Chen@Sun.COM
514*11260SMiao.Chen@Sun.COM agp_bind_pages_t bind;
515*11260SMiao.Chen@Sun.COM int ret, rval;
516*11260SMiao.Chen@Sun.COM
517*11260SMiao.Chen@Sun.COM bind.agpb_pgstart = gtt_offset / AGP_PAGE_SIZE;
518*11260SMiao.Chen@Sun.COM bind.agpb_pgcount = num_pages;
519*11260SMiao.Chen@Sun.COM bind.agpb_pages = pages;
520*11260SMiao.Chen@Sun.COM ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_PAGES_BIND,
521*11260SMiao.Chen@Sun.COM (intptr_t)&bind, FKIOCTL, kcred, &rval);
522*11260SMiao.Chen@Sun.COM if (ret) {
523*11260SMiao.Chen@Sun.COM DRM_ERROR("AGPIOC_PAGES_BIND failed ret %d", ret);
524*11260SMiao.Chen@Sun.COM return (ret);
525*11260SMiao.Chen@Sun.COM }
526*11260SMiao.Chen@Sun.COM return (0);
527*11260SMiao.Chen@Sun.COM }
528*11260SMiao.Chen@Sun.COM
529*11260SMiao.Chen@Sun.COM int
drm_agp_unbind_pages(drm_device_t * dev,unsigned long num_pages,uint32_t gtt_offset,uint32_t type)530*11260SMiao.Chen@Sun.COM drm_agp_unbind_pages(drm_device_t *dev,
531*11260SMiao.Chen@Sun.COM unsigned long num_pages,
532*11260SMiao.Chen@Sun.COM uint32_t gtt_offset,
533*11260SMiao.Chen@Sun.COM uint32_t type)
534*11260SMiao.Chen@Sun.COM {
535*11260SMiao.Chen@Sun.COM
536*11260SMiao.Chen@Sun.COM agp_unbind_pages_t unbind;
537*11260SMiao.Chen@Sun.COM int ret, rval;
538*11260SMiao.Chen@Sun.COM
539*11260SMiao.Chen@Sun.COM unbind.agpb_pgstart = gtt_offset / AGP_PAGE_SIZE;
540*11260SMiao.Chen@Sun.COM unbind.agpb_pgcount = num_pages;
541*11260SMiao.Chen@Sun.COM unbind.agpb_type = type;
542*11260SMiao.Chen@Sun.COM ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_PAGES_UNBIND,
543*11260SMiao.Chen@Sun.COM (intptr_t)&unbind, FKIOCTL, kcred, &rval);
544*11260SMiao.Chen@Sun.COM if (ret) {
545*11260SMiao.Chen@Sun.COM DRM_DEBUG("drm_agp_unbind_pages AGPIOC_PAGES_UNBIND failed");
546*11260SMiao.Chen@Sun.COM return (ret);
547*11260SMiao.Chen@Sun.COM }
548*11260SMiao.Chen@Sun.COM return (0);
549*11260SMiao.Chen@Sun.COM }
550*11260SMiao.Chen@Sun.COM
551*11260SMiao.Chen@Sun.COM /*
552*11260SMiao.Chen@Sun.COM * Certain Intel chipsets contains a global write buffer, and this can require
553*11260SMiao.Chen@Sun.COM * flushing from the drm or X.org to make sure all data has hit RAM before
554*11260SMiao.Chen@Sun.COM * initiating a GPU transfer, due to a lack of coherency with the integrated
555*11260SMiao.Chen@Sun.COM * graphics device and this buffer.
556*11260SMiao.Chen@Sun.COM */
557*11260SMiao.Chen@Sun.COM void
drm_agp_chipset_flush(struct drm_device * dev)558*11260SMiao.Chen@Sun.COM drm_agp_chipset_flush(struct drm_device *dev)
559*11260SMiao.Chen@Sun.COM {
560*11260SMiao.Chen@Sun.COM int ret, rval;
561*11260SMiao.Chen@Sun.COM
562*11260SMiao.Chen@Sun.COM DRM_DEBUG("agp_chipset_flush");
563*11260SMiao.Chen@Sun.COM ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_FLUSHCHIPSET,
564*11260SMiao.Chen@Sun.COM (intptr_t)0, FKIOCTL, kcred, &rval);
565*11260SMiao.Chen@Sun.COM if (ret != 0) {
566*11260SMiao.Chen@Sun.COM DRM_ERROR("Failed to drm_agp_chipset_flush ret %d", ret);
567*11260SMiao.Chen@Sun.COM }
568*11260SMiao.Chen@Sun.COM }
569*11260SMiao.Chen@Sun.COM
570*11260SMiao.Chen@Sun.COM /*
571*11260SMiao.Chen@Sun.COM * The pages are evict on suspend, so re-bind it at resume time
572*11260SMiao.Chen@Sun.COM */
573*11260SMiao.Chen@Sun.COM void
drm_agp_rebind(struct drm_device * dev)574*11260SMiao.Chen@Sun.COM drm_agp_rebind(struct drm_device *dev)
575*11260SMiao.Chen@Sun.COM {
576*11260SMiao.Chen@Sun.COM int ret, rval;
577*11260SMiao.Chen@Sun.COM
578*11260SMiao.Chen@Sun.COM if (!dev->agp) {
579*11260SMiao.Chen@Sun.COM return;
580*11260SMiao.Chen@Sun.COM }
581*11260SMiao.Chen@Sun.COM
582*11260SMiao.Chen@Sun.COM ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_PAGES_REBIND,
583*11260SMiao.Chen@Sun.COM (intptr_t)0, FKIOCTL, kcred, &rval);
584*11260SMiao.Chen@Sun.COM if (ret != 0) {
585*11260SMiao.Chen@Sun.COM DRM_ERROR("rebind failed %d", ret);
586*11260SMiao.Chen@Sun.COM }
587*11260SMiao.Chen@Sun.COM }
588