summaryrefslogtreecommitdiff
path: root/linux/drm_pci.h
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drm_pci.h')
-rw-r--r--linux/drm_pci.h232
1 files changed, 232 insertions, 0 deletions
diff --git a/linux/drm_pci.h b/linux/drm_pci.h
new file mode 100644
index 00000000..e6237499
--- /dev/null
+++ b/linux/drm_pci.h
@@ -0,0 +1,232 @@
+/**
+ * \file drm_pci.h
+ * \brief ioctl's to manage PCI memory
+ *
+ * \warning These interfaces aren't stable yet.
+ *
+ * \todo Implement the remaining ioctl's for the PCI pools.
+ * \todo Add support to map these buffers.
+ * \todo The wrappers here are so thin that they would be better off inlined..
+ *
+ * \author José Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+/*
+ * Copyright 2003 José Fonseca.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#define __NO_VERSION__
+#include <linux/pci.h>
+#include "drmP.h"
+
+
+/**********************************************************************/
+/** \name PCI memory */
+/*@{*/
+
+/**
+ * \brief Allocate a PCI consistent memory block, for DMA.
+ */
+void * DRM(pci_alloc)( drm_device_t *dev, size_t size,
+ dma_addr_t *busaddr )
+{
+ return pci_alloc_consistent( dev->pdev, size, busaddr );
+}
+
+/**
+ * \brief Free a PCI consistent memory block.
+ */
+void DRM(pci_free)( drm_device_t *dev, size_t size, void *cpuaddr,
+ dma_addr_t busaddr )
+{
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ pci_free_consistent( dev->pdev, size, cpuaddr, busaddr );
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name PCI memory pool */
+/*@{*/
+
+/**
+ * \brief Create a pool of PCI consistent memory blocks, for DMA.
+ *
+ * \return a handle on success, or NULL on failure.
+ *
+ * \note This is a minimalistic wrapper around Linux's pci_pool_create()
+ * function to ease porting to other OS's. More functionality can be exposed
+ * later if actually required by the drivers.
+ */
+void *DRM(pci_pool_create)( drm_device_t *dev, size_t size, size_t align )
+{
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ return pci_pool_create( "DRM", dev->pdev, size, align, 0, 0);
+}
+
+/**
+ * \brief Destroy a pool of PCI consistent memory blocks.
+ */
+void DRM(pci_pool_destroy)( drm_device_t *dev, void *entry )
+{
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ pci_pool_destroy( (struct pci_pool *)entry );
+}
+
+/**
+ * \brief Allocate a block from a PCI consistent memory block pool.
+ *
+ * \return the virtual address of a block on success, or NULL on failure.
+ */
+void *DRM(pci_pool_alloc)( void *entry, dma_addr_t *busaddr )
+{
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ return pci_pool_alloc( (struct pci_pool *)entry, 0, busaddr );
+}
+
+/**
+ * \brief Free a block back into a PCI consistent memory block pool.
+ */
+void DRM(pci_pool_free)( void *entry, void *cpuaddr, dma_addr_t busaddr )
+{
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ pci_pool_free( (struct pci_pool *)entry, cpuaddr, busaddr );
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Ioctl's */
+/*@{*/
+
+int DRM(pci_alloc_ioctl)( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_pci_mem_ioctl_t request;
+ drm_pci_mem_t *entry;
+
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ if ( copy_from_user( &request,
+ (drm_pci_mem_ioctl_t *)arg,
+ sizeof(request) ) )
+ return -EFAULT;
+
+ entry = DRM(alloc)( sizeof(*entry), DRM_MEM_DRIVER );
+ if ( !entry )
+ return -ENOMEM;
+
+ memset( entry, 0, sizeof(*entry) );
+
+ entry->cpuaddr = DRM(pci_alloc)( dev, request.size,
+ &entry->busaddr );
+
+ if ( !entry->cpuaddr ) {
+ DRM(free)( entry, sizeof(*entry), DRM_MEM_DRIVER );
+ return -ENOMEM;
+ }
+
+ entry->size = request.size;
+ request.busaddr = entry->busaddr;
+
+ if ( copy_to_user( (drm_pci_mem_ioctl_t *)arg,
+ &request,
+ sizeof(request) ) ) {
+ DRM(pci_free)( dev, entry->size, entry->cpuaddr,
+ entry->busaddr );
+ DRM(free)( entry, sizeof(*entry), DRM_MEM_DRIVER );
+ return -EFAULT;
+ }
+
+ list_add( (struct list_head *)entry, &dev->pci_mem );
+
+ return 0;
+}
+
+int DRM(pci_free_ioctl)( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_pci_mem_ioctl_t request;
+ struct list_head *ptr;
+ drm_pci_mem_t *entry;
+
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ if ( copy_from_user( &request,
+ (drm_pci_mem_ioctl_t *)arg,
+ sizeof(request) ) )
+ return -EFAULT;
+
+ list_for_each(ptr, &dev->pci_mem)
+ {
+ entry = list_entry(ptr, drm_pci_mem_t, list);
+ if( entry->busaddr == request.busaddr ) {
+ list_del(ptr);
+ DRM(pci_free)( dev, entry->size, entry->cpuaddr,
+ entry->busaddr );
+ DRM(free)( entry, sizeof(*entry), DRM_MEM_DRIVER );
+ return 0;
+ }
+ }
+
+ return -EFAULT;
+}
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Cleanup */
+/*@{*/
+
+/**
+ * \brief Called on driver exit to free the PCI memory allocated by userspace.
+ */
+void DRM(pci_cleanup)( drm_device_t *dev )
+{
+ struct list_head *ptr, *tmp;
+ drm_pci_mem_t *entry;
+
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ list_for_each_safe(ptr, tmp, &dev->pci_mem)
+ {
+ entry = list_entry(ptr, drm_pci_mem_t, list);
+ list_del(ptr);
+ DRM(pci_free)( dev, entry->size, entry->cpuaddr,
+ entry->busaddr );
+ DRM(free)( entry, sizeof(*entry), DRM_MEM_DRIVER );
+ }
+}
+
+/*@}*/