1450N/A/*
1450N/A * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
1450N/A */
1450N/A
1450N/A/**
1450N/A * \file drm_agpsupport.c
1450N/A * DRM support for AGP/GART backend
1450N/A *
1450N/A * \author Rickard E. (Rik) Faith <faith@valinux.com>
1450N/A * \author Gareth Hughes <gareth@valinux.com>
1450N/A */
1450N/A
1450N/A/*
1450N/A * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
1450N/A * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
1450N/A * Copyright (c) 2009, 2013, Intel Corporation.
1450N/A * All Rights Reserved.
1450N/A *
1450N/A * Permission is hereby granted, free of charge, to any person obtaining a
1450N/A * copy of this software and associated documentation files (the "Software"),
1450N/A * to deal in the Software without restriction, including without limitation
1450N/A * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1450N/A * and/or sell copies of the Software, and to permit persons to whom the
1450N/A * Software is furnished to do so, subject to the following conditions:
1450N/A *
1450N/A * The above copyright notice and this permission notice (including the next
1450N/A * paragraph) shall be included in all copies or substantial portions of the
1450N/A * Software.
1450N/A *
1450N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1450N/A * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1450N/A * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1450N/A * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
1450N/A * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1450N/A * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
1450N/A * OTHER DEALINGS IN THE SOFTWARE.
1450N/A */
1450N/A
1450N/A#include "drm.h"
1450N/A#include "drmP.h"
1450N/A
1450N/A#ifndef AGP_PAGE_SIZE
1450N/A#define AGP_PAGE_SIZE 4096
1450N/A#define AGP_PAGE_SHIFT 12
1450N/A#endif
1450N/A
1450N/A/*
1450N/A * The agpa_key field of struct agp_allocate_t actually is
1450N/A * an index to an array. It can be zero. But we will use
1450N/A * this agpa_key as a handle returned to userland. Generally,
1450N/A * 0 is not a valid value for a handle, so we add an offset
1450N/A * to the key to get a handle.
1450N/A */
1450N/A#define DRM_AGP_KEY_OFFSET 8
1450N/A
1450N/Avoid drm_agp_cleanup(struct drm_device *dev)
1450N/A{
1450N/A struct drm_agp_head *agp = dev->agp;
1450N/A
1450N/A (void) ldi_close(agp->agpgart_lh, FEXCL, kcred);
1450N/A ldi_ident_release(agp->agpgart_li);
1450N/A}
1450N/A
1450N/A/**
1450N/A * Get AGP information.
1450N/A *
1450N/A * \param inode device inode.
1450N/A * \param file_priv DRM file private.
1450N/A * \param cmd command.
1450N/A * \param arg pointer to a (output) drm_agp_info structure.
1450N/A * \return zero on success or a negative number on failure.
1450N/A *
1450N/A * Verifies the AGP device has been initialized and acquired and fills in the
1450N/A * drm_agp_info structure with the information in drm_agp_head::agp_info.
1450N/A */
1450N/Aint drm_agp_info(struct drm_device *dev, struct drm_agp_info *info)
1450N/A{
1450N/A agp_info_t *agpinfo;
1450N/A
1450N/A if (!dev->agp || !dev->agp->acquired)
1450N/A return -EINVAL;
1450N/A
1450N/A agpinfo = &dev->agp->agp_info;
1450N/A info->agp_version_major = agpinfo->agpi_version.agpv_major;
1450N/A info->agp_version_minor = agpinfo->agpi_version.agpv_minor;
1450N/A info->mode = agpinfo->agpi_mode;
1450N/A info->aperture_base = agpinfo->agpi_aperbase;
1450N/A info->aperture_size = agpinfo->agpi_apersize * 1024 * 1024;
1450N/A info->memory_allowed = agpinfo->agpi_pgtotal << PAGE_SHIFT;
1450N/A info->memory_used = agpinfo->agpi_pgused << PAGE_SHIFT;
1450N/A info->id_vendor = agpinfo->agpi_devid & 0xffff;
1450N/A info->id_device = agpinfo->agpi_devid >> 16;
1450N/A
1450N/A return 0;
1450N/A}
1450N/A
1450N/A/* LINTED */
1450N/Aint drm_agp_info_ioctl(DRM_IOCTL_ARGS)
1450N/A{
1450N/A struct drm_agp_info *info = data;
1450N/A int err;
1450N/A
1450N/A err = drm_agp_info(dev, info);
1450N/A if (err)
1450N/A return err;
1450N/A
1450N/A return 0;
1450N/A}
1450N/A
1450N/A/**
1450N/A * Acquire the AGP device.
1450N/A *
1450N/A * \param dev DRM device that is to acquire AGP.
1450N/A * \return zero on success or a negative number on failure.
1450N/A *
1450N/A * Verifies the AGP device hasn't been acquired before and calls
1450N/A * \c agp_backend_acquire.
1450N/A */
1450N/Aint drm_agp_acquire(struct drm_device * dev)
1450N/A{
1450N/A if (!dev->agp)
1450N/A return -ENODEV;
1450N/A if (dev->agp->acquired)
1450N/A return -EBUSY;
1450N/A {
1450N/A int ret, rval;
1450N/A if (ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_ACQUIRE,
1450N/A (uintptr_t)0, FKIOCTL, kcred, &rval)) {
1450N/A DRM_ERROR("AGPIOC_ACQUIRE failed");
1450N/A return -ret;
1450N/A }
1450N/A }
1450N/A dev->agp->acquired = 1;
1450N/A return 0;
1450N/A}
1450N/A
1450N/A/**
1450N/A * Acquire the AGP device (ioctl).
1450N/A *
1450N/A * \param inode device inode.
1450N/A * \param file_priv DRM file private.
1450N/A * \param cmd command.
1450N/A * \param arg user argument.
1450N/A * \return zero on success or a negative number on failure.
1450N/A *
1450N/A * Verifies the AGP device hasn't been acquired before and calls
1450N/A * \c agp_backend_acquire.
1450N/A */
1450N/A/* LINTED */
1450N/Aint drm_agp_acquire_ioctl(DRM_IOCTL_ARGS)
1450N/A{
1450N/A return drm_agp_acquire((struct drm_device *) file->minor->dev);
1450N/A}
1450N/A
1450N/A/**
1450N/A * Release the AGP device.
1450N/A *
1450N/A * \param dev DRM device that is to release AGP.
1450N/A * \return zero on success or a negative number on failure.
1450N/A *
1450N/A * Verifies the AGP device has been acquired and calls \c agp_backend_release.
1450N/A */
1450N/Aint drm_agp_release(struct drm_device * dev)
1450N/A{
1450N/A if (!dev->agp || !dev->agp->acquired)
1450N/A return -EINVAL;
1450N/A {
1450N/A int ret, rval;
1450N/A if (ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_RELEASE,
1450N/A (intptr_t)0, FKIOCTL, kcred, &rval)) {
1450N/A DRM_ERROR("AGPIOC_RELEASE failed");
1450N/A return -ret;
1450N/A }
1450N/A }
1450N/A dev->agp->acquired = 0;
1450N/A return 0;
1450N/A}
1450N/A
1450N/A/* LINTED */
1450N/Aint drm_agp_release_ioctl(DRM_IOCTL_ARGS)
1450N/A{
1450N/A return drm_agp_release(dev);
1450N/A}
1450N/A
1450N/A/**
1450N/A * Enable the AGP bus.
1450N/A *
1450N/A * \param dev DRM device that has previously acquired AGP.
1450N/A * \param mode Requested AGP mode.
1450N/A * \return zero on success or a negative number on failure.
1450N/A *
1450N/A * Verifies the AGP device has been acquired but not enabled, and calls
1450N/A * \c agp_enable.
1450N/A */
1450N/Aint drm_agp_enable(struct drm_device * dev, struct drm_agp_mode mode)
1450N/A{
1450N/A if (!dev->agp || !dev->agp->acquired)
1450N/A return -EINVAL;
1450N/A
1450N/A dev->agp->mode = mode.mode;
1450N/A {
1450N/A agp_setup_t setup;
1450N/A int ret, rval;
1450N/A setup.agps_mode = (uint32_t)mode.mode;
1450N/A if (ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_SETUP,
1450N/A (intptr_t)&setup, FKIOCTL, kcred, &rval)) {
1450N/A DRM_ERROR("AGPIOC_SETUP failed");
1450N/A return -ret;
1450N/A }
1450N/A }
1450N/A dev->agp->enabled = 1;
1450N/A return 0;
1450N/A}
1450N/A
1450N/A/* LINTED */
1450N/Aint drm_agp_enable_ioctl(DRM_IOCTL_ARGS)
1450N/A{
1450N/A struct drm_agp_mode *mode = data;
1450N/A
1450N/A return drm_agp_enable(dev, *mode);
1450N/A}
1450N/A
1450N/A/**
1450N/A * Allocate AGP memory.
1450N/A *
1450N/A * \param inode device inode.
1450N/A * \param file_priv file private pointer.
1450N/A * \param cmd command.
1450N/A * \param arg pointer to a drm_agp_buffer structure.
1450N/A * \return zero on success or a negative number on failure.
1450N/A *
1450N/A * Verifies the AGP device is present and has been acquired, allocates the
1450N/A * memory via alloc_agp() and creates a drm_agp_mem entry for it.
1450N/A */
1450N/Aint drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
1450N/A{
1450N/A struct drm_agp_mem *entry;
1450N/A agp_allocate_t alloc;
1450N/A unsigned long pages;
1450N/A int ret, rval;
1450N/A
1450N/A if (!dev->agp || !dev->agp->acquired)
1450N/A return -EINVAL;
1450N/A if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
1450N/A return -ENOMEM;
1450N/A
1450N/A (void) memset(entry, 0, sizeof(*entry));
1450N/A
1450N/A pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
1450N/A
1450N/A alloc.agpa_pgcount = (uint32_t) pages;
1450N/A alloc.agpa_type = AGP_NORMAL;
1450N/A ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_ALLOCATE,
1450N/A (intptr_t)&alloc, FKIOCTL, kcred, &rval);
1450N/A if (ret) {
1450N/A DRM_ERROR("AGPIOC_ALLOCATE failed");
1450N/A kfree(entry, sizeof (*entry));
1450N/A return -ret;
1450N/A }
1450N/A
1450N/A entry->handle = alloc.agpa_key + DRM_AGP_KEY_OFFSET;
1450N/A entry->bound = 0;
1450N/A entry->pages = (int) pages;
1450N/A list_add(&entry->head, &dev->agp->memory, (caddr_t)entry);
1450N/A
1450N/A request->handle = entry->handle;
1450N/A request->physical = alloc.agpa_physical;
1450N/A
1450N/A return 0;
1450N/A}
1450N/A
1450N/A/* LINTED */
1450N/Aint drm_agp_alloc_ioctl(DRM_IOCTL_ARGS)
1450N/A{
1450N/A struct drm_agp_buffer *request = data;
1450N/A
1450N/A return drm_agp_alloc(dev, request);
1450N/A}
1450N/A
1450N/A/**
1450N/A * Search for the AGP memory entry associated with a handle.
1450N/A *
1450N/A * \param dev DRM device structure.
1450N/A * \param handle AGP memory handle.
1450N/A * \return pointer to the drm_agp_mem structure associated with \p handle.
1450N/A *
1450N/A * Walks through drm_agp_head::memory until finding a matching handle.
1450N/A */
1450N/Astatic struct drm_agp_mem *drm_agp_lookup_entry(struct drm_device * dev,
1450N/A unsigned long handle)
1450N/A{
1450N/A struct drm_agp_mem *entry;
1450N/A
1450N/A list_for_each_entry(entry, struct drm_agp_mem, &dev->agp->memory, head) {
1450N/A if (entry->handle == handle)
1450N/A return entry;
1450N/A }
1450N/A return NULL;
1450N/A}
1450N/A
1450N/A/**
1450N/A * Unbind AGP memory from the GATT (ioctl).
1450N/A *
1450N/A * \param inode device inode.
1450N/A * \param file_priv DRM file private.
1450N/A * \param cmd command.
1450N/A * \param arg pointer to a drm_agp_binding structure.
1450N/A * \return zero on success or a negative number on failure.
1450N/A *
1450N/A * Verifies the AGP device is present and acquired, looks-up the AGP memory
1450N/A * entry and passes it to the unbind_agp() function.
1450N/A */
1450N/Aint drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request)
1450N/A{
1450N/A struct drm_agp_mem *entry;
1450N/A int ret;
1450N/A
1450N/A if (!dev->agp || !dev->agp->acquired)
1450N/A return -EINVAL;
1450N/A if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
1450N/A return -EINVAL;
1450N/A if (!entry->bound)
1450N/A return -EINVAL;
1450N/A {
1450N/A agp_unbind_t unbind;
1450N/A int rval;
1450N/A unbind.agpu_pri = 0;
1450N/A unbind.agpu_key = (uintptr_t)entry->handle - DRM_AGP_KEY_OFFSET;
1450N/A if (ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_UNBIND,
1450N/A (intptr_t)&unbind, FKIOCTL, kcred, &rval)) {
1450N/A DRM_ERROR("AGPIOC_UNBIND failed");
1450N/A return -ret;
1450N/A }
1450N/A }
1450N/A entry->bound = 0;
1450N/A return ret;
1450N/A}
1450N/A
1450N/A/* LINTED */
1450N/Aint drm_agp_unbind_ioctl(DRM_IOCTL_ARGS)
1450N/A{
1450N/A struct drm_agp_binding *request = data;
1450N/A
1450N/A return drm_agp_unbind(dev, request);
1450N/A}
1450N/A
1450N/A/**
1450N/A * Bind AGP memory into the GATT (ioctl)
1450N/A *
1450N/A * \param inode device inode.
1450N/A * \param file_priv DRM file private.
1450N/A * \param cmd command.
1450N/A * \param arg pointer to a drm_agp_binding structure.
1450N/A * \return zero on success or a negative number on failure.
1450N/A *
1450N/A * Verifies the AGP device is present and has been acquired and that no memory
1450N/A * is currently bound into the GATT. Looks-up the AGP memory entry and passes
1450N/A * it to bind_agp() function.
1450N/A */
1450N/Aint drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request)
1450N/A{
1450N/A struct drm_agp_mem *entry;
1450N/A int retcode;
1450N/A int page;
1450N/A
1450N/A if (!dev->agp || !dev->agp->acquired)
1450N/A return -EINVAL;
1450N/A if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
1450N/A return -EINVAL;
1450N/A if (entry->bound)
1450N/A return -EINVAL;
1450N/A page = (request->offset + PAGE_SIZE - 1) / PAGE_SIZE;
1450N/A {
1450N/A uint_t key = (uintptr_t)entry->handle - DRM_AGP_KEY_OFFSET;
1450N/A if (retcode = drm_agp_bind_memory(key, page, dev)) {
1450N/A DRM_ERROR("failed key=0x%x, page=0x%x, "
1450N/A "agp_base=0x%lx", key, page, dev->agp->base);
1450N/A return retcode;
1450N/A }
1450N/A }
1450N/A entry->bound = dev->agp->base + (page << PAGE_SHIFT);
1450N/A DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n",
1450N/A dev->agp->base, entry->bound);
1450N/A return 0;
1450N/A}
1450N/A
1450N/A/* LINTED */
1450N/Aint drm_agp_bind_ioctl(DRM_IOCTL_ARGS)
1450N/A{
1450N/A struct drm_agp_binding *request = data;
1450N/A
1450N/A return drm_agp_bind(dev, request);
1450N/A}
1450N/A
1450N/A/**
1450N/A * Free AGP memory (ioctl).
1450N/A *
1450N/A * \param inode device inode.
1450N/A * \param file_priv DRM file private.
1450N/A * \param cmd command.
1450N/A * \param arg pointer to a drm_agp_buffer structure.
1450N/A * \return zero on success or a negative number on failure.
1450N/A *
1450N/A * Verifies the AGP device is present and has been acquired and looks up the
1450N/A * AGP memory entry. If the memory it's currently bound, unbind it via
1450N/A * unbind_agp(). Frees it via free_agp() as well as the entry itself
1450N/A * and unlinks from the doubly linked list it's inserted in.
1450N/A */
1450N/Aint drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
1450N/A{
1450N/A struct drm_agp_mem *entry;
1450N/A
1450N/A if (!dev->agp || !dev->agp->acquired)
1450N/A return -EINVAL;
1450N/A if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
1450N/A return -EINVAL;
1450N/A if (entry->bound)
1450N/A (void) drm_agp_unbind_memory(request->handle, dev);
1450N/A
1450N/A list_del(&entry->head);
1450N/A {
1450N/A int agpu_key = (uintptr_t)entry->handle - DRM_AGP_KEY_OFFSET;
1450N/A int ret, rval;
1450N/A ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_DEALLOCATE,
1450N/A (intptr_t)agpu_key, FKIOCTL, kcred, &rval);
1450N/A if (ret) {
1450N/A DRM_ERROR("AGPIOC_DEALLOCATE failed,"
1450N/A "akey=%d, ret=%d", agpu_key, ret);
1450N/A return -ret;
1450N/A }
1450N/A }
1450N/A kfree(entry, sizeof (*entry));
1450N/A return 0;
1450N/A}
1450N/A
1450N/A/* LINTED */
1450N/Aint drm_agp_free_ioctl(DRM_IOCTL_ARGS)
1450N/A{
1450N/A struct drm_agp_buffer *request = data;
1450N/A
1450N/A return drm_agp_free(dev, request);
1450N/A}
1450N/A
1450N/A/**
1450N/A * Initialize the AGP resources.
1450N/A *
1450N/A * \return pointer to a drm_agp_head structure.
1450N/A *
1450N/A * Gets the drm_agp_t structure which is made available by the agpgart module
1450N/A * via the inter_module_* functions. Creates and initializes a drm_agp_head
1450N/A * structure.
1450N/A */
1450N/Astruct drm_agp_head *drm_agp_init(struct drm_device *dev)
1450N/A{
1450N/A struct drm_agp_head *head = NULL;
1450N/A int ret, rval;
1450N/A
1450N/A if (!(head = kmalloc(sizeof(*head), GFP_KERNEL)))
1450N/A return NULL;
1450N/A (void) memset((void *)head, 0, sizeof(*head));
1450N/A ret = ldi_ident_from_dip(dev->devinfo, &head->agpgart_li);
1450N/A if (ret) {
1450N/A DRM_ERROR("failed to get layerd ident, ret=%d", ret);
1450N/A goto err_1;
1450N/A }
1450N/A
1450N/A ret = ldi_open_by_name(AGP_DEVICE, FEXCL, kcred,
1450N/A &head->agpgart_lh, head->agpgart_li);
1450N/A if (ret) {
1450N/A DRM_ERROR("failed to open %s, ret=%d", AGP_DEVICE, ret);
1450N/A goto err_2;
1450N/A }
1450N/A
1450N/A ret = ldi_ioctl(head->agpgart_lh, AGPIOC_INFO,
1450N/A (intptr_t)&head->agp_info, FKIOCTL, kcred, &rval);
1450N/A if (ret) {
1450N/A DRM_ERROR("failed to get agpinfo, ret=%d", ret);
1450N/A goto err_3;
1450N/A }
1450N/A INIT_LIST_HEAD(&head->memory);
1450N/A head->base = head->agp_info.agpi_aperbase;
1450N/A return head;
1450N/A
1450N/Aerr_3:
1450N/A (void) ldi_close(head->agpgart_lh, FEXCL, kcred);
1450N/Aerr_2:
1450N/A ldi_ident_release(head->agpgart_li);
1450N/Aerr_1:
1450N/A kfree(head, sizeof(*head));
1450N/A return NULL;
1450N/A}
1450N/A
1450N/A/* LINTED */
1450N/Avoid *drm_agp_allocate_memory(size_t pages, uint32_t type, struct drm_device *dev)
1450N/A{
1450N/A return NULL;
1450N/A}
1450N/A
1450N/A/* LINTED */
1450N/Aint drm_agp_free_memory(agp_allocate_t *handle, struct drm_device *dev)
1450N/A{
1450N/A return 1;
1450N/A}
1450N/A
1450N/Aint drm_agp_bind_memory(unsigned int key, uint32_t start, struct drm_device *dev)
1450N/A{
1450N/A agp_bind_t bind;
1450N/A int ret, rval;
1450N/A
1450N/A bind.agpb_pgstart = start;
1450N/A bind.agpb_key = key;
1450N/A if (ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_BIND,
1450N/A (intptr_t)&bind, FKIOCTL, kcred, &rval)) {
1450N/A DRM_DEBUG("AGPIOC_BIND failed");
1450N/A return -ret;
1450N/A }
1450N/A return 0;
1450N/A}
1450N/A
1450N/Aint drm_agp_unbind_memory(unsigned long handle, struct drm_device *dev)
1450N/A{
1450N/A struct drm_agp_mem *entry;
1450N/A agp_unbind_t unbind;
1450N/A int ret, rval;
1450N/A
1450N/A if (!dev->agp || !dev->agp->acquired)
1450N/A return -EINVAL;
1450N/A
1450N/A entry = drm_agp_lookup_entry(dev, handle);
1450N/A if (!entry || !entry->bound)
1450N/A return -EINVAL;
1450N/A
1450N/A unbind.agpu_pri = 0;
1450N/A unbind.agpu_key = (uintptr_t)entry->handle - DRM_AGP_KEY_OFFSET;
1450N/A if (ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_UNBIND,
1450N/A (intptr_t)&unbind, FKIOCTL, kcred, &rval)) {
1450N/A DRM_ERROR("AGPIO_UNBIND failed");
1450N/A return -ret;
1450N/A }
1450N/A entry->bound = 0;
1450N/A return 0;
1450N/A}
1450N/A
1450N/A/**
1450N/A * Binds a collection of pages into AGP memory at the given offset, returning
1450N/A * the AGP memory structure containing them.
1450N/A *
1450N/A * No reference is held on the pages during this time -- it is up to the
1450N/A * caller to handle that.
1450N/A */
1450N/Aint
1450N/Adrm_agp_bind_pages(struct drm_device *dev,
1450N/A pfn_t *pages,
1450N/A unsigned long num_pages,
1450N/A uint32_t gtt_offset,
1450N/A unsigned int agp_type)
1450N/A{
1450N/A agp_gtt_info_t bind;
1450N/A int ret, rval;
1450N/A
1450N/A bind.agp_pgstart = gtt_offset / AGP_PAGE_SIZE;
1450N/A bind.agp_npage = num_pages;
1450N/A bind.agp_phyaddr = pages;
1450N/A bind.agp_flags = agp_type;
1450N/A
1450N/A ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_PAGES_BIND,
1450N/A (intptr_t)&bind, FKIOCTL, kcred, &rval);
1450N/A if (ret) {
1450N/A DRM_ERROR("AGPIOC_PAGES_BIND failed ret %d", ret);
1450N/A return -ret;
1450N/A }
1450N/A return 0;
1450N/A}
1450N/A
1450N/Aint
1450N/Adrm_agp_unbind_pages(struct drm_device *dev,
1450N/A pfn_t *pages,
1450N/A unsigned long num_pages,
1450N/A uint32_t gtt_offset,
1450N/A pfn_t scratch,
1450N/A uint32_t type)
1450N/A{
1450N/A agp_gtt_info_t unbind;
1450N/A int ret, rval;
1450N/A
1450N/A unbind.agp_pgstart = gtt_offset / AGP_PAGE_SIZE;
1450N/A unbind.agp_npage = num_pages;
1450N/A unbind.agp_type = type;
1450N/A unbind.agp_phyaddr = pages;
1450N/A unbind.agp_scratch = scratch;
1450N/A
1450N/A ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_PAGES_UNBIND,
1450N/A (intptr_t)&unbind, FKIOCTL, kcred, &rval);
1450N/A if (ret) {
1450N/A DRM_ERROR("AGPIOC_PAGES_UNBIND failed %d", ret);
1450N/A return -ret;
1450N/A }
1450N/A return 0;
1450N/A}
1450N/A
1450N/Avoid drm_agp_chipset_flush(struct drm_device *dev)
1450N/A{
1450N/A int ret, rval;
1450N/A
1450N/A ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_FLUSHCHIPSET,
1450N/A (intptr_t)0, FKIOCTL, kcred, &rval);
1450N/A if (ret)
1450N/A DRM_ERROR("AGPIOC_FLUSHCHIPSET failed, ret=%d", ret);
1450N/A}
1450N/A
1450N/Aint
1450N/Adrm_agp_rw_gtt(struct drm_device *dev,
1450N/A unsigned long num_pages,
1450N/A uint32_t gtt_offset,
1450N/A void *gttp,
1450N/A uint32_t type)
1450N/A{
1450N/A agp_rw_gtt_t gtt_info;
1450N/A int ret, rval;
1450N/A
1450N/A gtt_info.pgstart = gtt_offset / AGP_PAGE_SIZE;
1450N/A gtt_info.pgcount = num_pages;
1450N/A gtt_info.addr = gttp;
1450N/A /* read = 0 write = 1 */
1450N/A gtt_info.type = type;
1450N/A ret = ldi_ioctl(dev->agp->agpgart_lh, AGPIOC_RW_GTT,
1450N/A (intptr_t)&gtt_info, FKIOCTL, kcred, &rval);
1450N/A if (ret) {
1450N/A DRM_ERROR("AGPIOC_RW_GTT failed %d", ret);
1450N/A return -ret;
1450N/A }
1450N/A return 0;
1450N/A}