Added IOCTL for writing 2D DMA command buffers over PCI. Bumped minor
authorThomas Hellstrom <unichrome@shipmail.org>
Tue, 7 Sep 2004 16:48:44 +0000 (16:48 +0000)
committerThomas Hellstrom <unichrome@shipmail.org>
Tue, 7 Sep 2004 16:48:44 +0000 (16:48 +0000)
    version number.

shared-core/via_dma.c
shared-core/via_drm.h
shared-core/via_drv.c
shared-core/via_drv.h
shared/via_dma.c
shared/via_drm.h
shared/via_drv.c
shared/via_drv.h

index 83c14cf..c11652c 100644 (file)
@@ -16,6 +16,8 @@
 #include "via_drm.h"
 #include "via_drv.h"
 
+#define VIA_2D_CMD 0xF0000000
+
 static void via_cmdbuf_start(drm_via_private_t * dev_priv);
 static void via_cmdbuf_pause(drm_via_private_t * dev_priv);
 static void via_cmdbuf_reset(drm_via_private_t * dev_priv);
@@ -223,6 +225,92 @@ int via_cmdbuffer( DRM_IOCTL_ARGS )
        return 0;
 }
 
+static int via_parse_pci_cmdbuffer( drm_device_t *dev, const char *buf, 
+                                   unsigned int size )
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+       uint32_t offset, value;
+       const uint32_t *regbuf = (uint32_t *)buf;
+       unsigned int i;
+
+       size >>=3 ;
+       for (i=0; i<size; ++i) {
+               offset = *regbuf; 
+               regbuf += 2;
+               if ((offset > ((0x7FF >> 2) | VIA_2D_CMD)) && 
+                   (offset < ((0xC00 >> 2) | VIA_2D_CMD)) ) {
+                       DRM_DEBUG("Attempt to access Burst Command Area.\n");
+                       return DRM_ERR( EINVAL );
+               } else if (offset > ((0xDFF >> 2) | VIA_2D_CMD)) {
+                       DRM_DEBUG("Attempt to access DMA or VGA registers.\n");
+                       return DRM_ERR( EINVAL );
+               }
+       }
+                       
+       regbuf = (uint32_t *)buf;
+       for ( i=0; i<size; ++i ) {
+               offset = (*regbuf++ & ~VIA_2D_CMD) << 2;
+               value = *regbuf++;
+               VIA_WRITE( offset, value );
+       }
+       return 0;
+}
+               
+static int via_dispatch_pci_cmdbuffer(drm_device_t *dev, 
+                                     drm_via_cmdbuffer_t *cmd )
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+       char *hugebuf;
+       int ret;
+
+       /*
+        * We must be able to parse the buffer all at a time, so as
+        * to return an error on an invalid operation without doing
+        * anything.
+        * Small buffers must, on the other hand be handled fast.
+        */
+
+       if ( cmd->size > VIA_MAX_PCI_SIZE ) {
+               return DRM_ERR( ENOMEM );
+       } else if ( cmd->size > VIA_PREALLOCATED_PCI_SIZE ) {
+         if (NULL == (hugebuf = (char *) kmalloc( cmd-> size, GFP_KERNEL )))
+                       return DRM_ERR( ENOMEM );
+               DRM_COPY_FROM_USER( hugebuf, cmd->buf, cmd->size );
+               ret = via_parse_pci_cmdbuffer( dev, hugebuf, cmd->size );
+               kfree( hugebuf );
+       } else {
+               DRM_COPY_FROM_USER( dev_priv->pci_buf, cmd->buf, cmd->size );
+               ret = via_parse_pci_cmdbuffer( dev, dev_priv->pci_buf, cmd->size );
+       }
+       return ret;
+}
+
+
+
+int via_pci_cmdbuffer( DRM_IOCTL_ARGS )
+{
+       DRM_DEVICE;
+       drm_via_cmdbuffer_t cmdbuf;
+       int ret;
+
+       DRM_COPY_FROM_USER_IOCTL( cmdbuf, (drm_via_cmdbuffer_t *)data, 
+                       sizeof(cmdbuf) );
+
+       DRM_DEBUG("via_pci_cmdbuffer, buf %p size %lu\n", cmdbuf.buf, cmdbuf.size);
+
+       if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+               DRM_ERROR("via_pci_cmdbuffer called without lock held\n");
+               return DRM_ERR(EINVAL);
+       }
+
+       ret = via_dispatch_pci_cmdbuffer( dev, &cmdbuf );
+       if (ret) {
+               return ret;
+       }
+
+       return 0;
+}
+
 
 
 
index 5325f62..ddc89f8 100644 (file)
@@ -38,6 +38,8 @@
 #define VIA_NR_XVMC_PORTS               10
 #define VIA_NR_XVMC_LOCKS               5
 #define VIA_MAX_CACHELINE_SIZE          64
+#define VIA_PREALLOCATED_PCI_SIZE       16384
+#define VIA_MAX_PCI_SIZE                65536
 #define XVMCLOCKPTR(saPriv,lockNo)                                     \
         ((volatile int *)(((((unsigned long) (saPriv)->XvMCLockArea) + \
                             (VIA_MAX_CACHELINE_SIZE - 1)) &             \
 #define DRM_IOCTL_VIA_MAP_INIT DRM_IOWR(0x44, drm_via_init_t)
 #define DRM_IOCTL_VIA_DEC_FUTEX DRM_IOW(0x45, drm_via_futex_t)
 #define DRM_IOCTL_VIA_DMA_INIT DRM_IOWR(0x47, drm_via_dma_init_t)
-#define DRM_IOCTL_VIA_CMDBUFFER        DRM_IOWR(0x48, drm_via_dma_init_t)
+#define DRM_IOCTL_VIA_CMDBUFFER        DRM_IOW(0x48, drm_via_cmdbuffer_t)
 #define DRM_IOCTL_VIA_FLUSH    DRM_IO(0x49)
+#define DRM_IOCTL_VIA_PCICMD   DRM_IOW(0x4A, drm_via_cmdbuffer_t)
+
 
 /* Indices into buf.Setup where various bits of state are mirrored per
  * context and per buffer.  These can be fired at the card as a unit,
@@ -200,6 +204,7 @@ int via_decoder_futex( DRM_IOCTL_ARGS );
 int via_dma_init( DRM_IOCTL_ARGS );
 int via_cmdbuffer( DRM_IOCTL_ARGS );
 int via_flush_ioctl( DRM_IOCTL_ARGS );
+int via_pci_cmdbuffer( DRM_IOCTL_ARGS );
 
 #endif
 #endif /* _VIA_DRM_H_ */
index b3119f6..8c4e748 100644 (file)
@@ -21,6 +21,7 @@
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
+
 #include <linux/config.h>
 #include "via.h"
 #include "drmP.h"
 
 #define DRIVER_NAME            "via"
 #define DRIVER_DESC            "VIA Unichrome"
-#define DRIVER_DATE            "20040819"
+#define DRIVER_DATE            "20040907"
 
 #define DRIVER_MAJOR           1
-#define DRIVER_MINOR           4
+#define DRIVER_MINOR           5
 #define DRIVER_PATCHLEVEL      0
 
 
@@ -47,7 +48,8 @@
         [DRM_IOCTL_NR(DRM_IOCTL_VIA_DEC_FUTEX)] = { via_decoder_futex, 1, 0}, \
         [DRM_IOCTL_NR(DRM_IOCTL_VIA_DMA_INIT)] = { via_dma_init, 1, 0}, \
         [DRM_IOCTL_NR(DRM_IOCTL_VIA_CMDBUFFER)] = { via_cmdbuffer, 1, 0}, \
-        [DRM_IOCTL_NR(DRM_IOCTL_VIA_FLUSH)] = { via_flush_ioctl, 1, 0}
+       [DRM_IOCTL_NR(DRM_IOCTL_VIA_FLUSH)] = { via_flush_ioctl, 1, 0}, \
+        [DRM_IOCTL_NR(DRM_IOCTL_VIA_PCICMD)] = { via_pci_cmdbuffer, 1, 0}
 
 
 #define __HAVE_COUNTERS                0
index dd4a370..39ccf0b 100644 (file)
@@ -46,6 +46,7 @@ typedef struct drm_via_private {
         uint32_t * last_pause_ptr;
         volatile uint32_t * hw_addr_ptr;
         drm_via_ring_buffer_t ring;
+       char pci_buf[VIA_PREALLOCATED_PCI_SIZE];
 } drm_via_private_t;
 
  
index 83c14cf..c11652c 100644 (file)
@@ -16,6 +16,8 @@
 #include "via_drm.h"
 #include "via_drv.h"
 
+#define VIA_2D_CMD 0xF0000000
+
 static void via_cmdbuf_start(drm_via_private_t * dev_priv);
 static void via_cmdbuf_pause(drm_via_private_t * dev_priv);
 static void via_cmdbuf_reset(drm_via_private_t * dev_priv);
@@ -223,6 +225,92 @@ int via_cmdbuffer( DRM_IOCTL_ARGS )
        return 0;
 }
 
+static int via_parse_pci_cmdbuffer( drm_device_t *dev, const char *buf, 
+                                   unsigned int size )
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+       uint32_t offset, value;
+       const uint32_t *regbuf = (uint32_t *)buf;
+       unsigned int i;
+
+       size >>=3 ;
+       for (i=0; i<size; ++i) {
+               offset = *regbuf; 
+               regbuf += 2;
+               if ((offset > ((0x7FF >> 2) | VIA_2D_CMD)) && 
+                   (offset < ((0xC00 >> 2) | VIA_2D_CMD)) ) {
+                       DRM_DEBUG("Attempt to access Burst Command Area.\n");
+                       return DRM_ERR( EINVAL );
+               } else if (offset > ((0xDFF >> 2) | VIA_2D_CMD)) {
+                       DRM_DEBUG("Attempt to access DMA or VGA registers.\n");
+                       return DRM_ERR( EINVAL );
+               }
+       }
+                       
+       regbuf = (uint32_t *)buf;
+       for ( i=0; i<size; ++i ) {
+               offset = (*regbuf++ & ~VIA_2D_CMD) << 2;
+               value = *regbuf++;
+               VIA_WRITE( offset, value );
+       }
+       return 0;
+}
+               
+static int via_dispatch_pci_cmdbuffer(drm_device_t *dev, 
+                                     drm_via_cmdbuffer_t *cmd )
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+       char *hugebuf;
+       int ret;
+
+       /*
+        * We must be able to parse the buffer all at a time, so as
+        * to return an error on an invalid operation without doing
+        * anything.
+        * Small buffers must, on the other hand be handled fast.
+        */
+
+       if ( cmd->size > VIA_MAX_PCI_SIZE ) {
+               return DRM_ERR( ENOMEM );
+       } else if ( cmd->size > VIA_PREALLOCATED_PCI_SIZE ) {
+         if (NULL == (hugebuf = (char *) kmalloc( cmd-> size, GFP_KERNEL )))
+                       return DRM_ERR( ENOMEM );
+               DRM_COPY_FROM_USER( hugebuf, cmd->buf, cmd->size );
+               ret = via_parse_pci_cmdbuffer( dev, hugebuf, cmd->size );
+               kfree( hugebuf );
+       } else {
+               DRM_COPY_FROM_USER( dev_priv->pci_buf, cmd->buf, cmd->size );
+               ret = via_parse_pci_cmdbuffer( dev, dev_priv->pci_buf, cmd->size );
+       }
+       return ret;
+}
+
+
+
+int via_pci_cmdbuffer( DRM_IOCTL_ARGS )
+{
+       DRM_DEVICE;
+       drm_via_cmdbuffer_t cmdbuf;
+       int ret;
+
+       DRM_COPY_FROM_USER_IOCTL( cmdbuf, (drm_via_cmdbuffer_t *)data, 
+                       sizeof(cmdbuf) );
+
+       DRM_DEBUG("via_pci_cmdbuffer, buf %p size %lu\n", cmdbuf.buf, cmdbuf.size);
+
+       if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+               DRM_ERROR("via_pci_cmdbuffer called without lock held\n");
+               return DRM_ERR(EINVAL);
+       }
+
+       ret = via_dispatch_pci_cmdbuffer( dev, &cmdbuf );
+       if (ret) {
+               return ret;
+       }
+
+       return 0;
+}
+
 
 
 
index 5325f62..ddc89f8 100644 (file)
@@ -38,6 +38,8 @@
 #define VIA_NR_XVMC_PORTS               10
 #define VIA_NR_XVMC_LOCKS               5
 #define VIA_MAX_CACHELINE_SIZE          64
+#define VIA_PREALLOCATED_PCI_SIZE       16384
+#define VIA_MAX_PCI_SIZE                65536
 #define XVMCLOCKPTR(saPriv,lockNo)                                     \
         ((volatile int *)(((((unsigned long) (saPriv)->XvMCLockArea) + \
                             (VIA_MAX_CACHELINE_SIZE - 1)) &             \
 #define DRM_IOCTL_VIA_MAP_INIT DRM_IOWR(0x44, drm_via_init_t)
 #define DRM_IOCTL_VIA_DEC_FUTEX DRM_IOW(0x45, drm_via_futex_t)
 #define DRM_IOCTL_VIA_DMA_INIT DRM_IOWR(0x47, drm_via_dma_init_t)
-#define DRM_IOCTL_VIA_CMDBUFFER        DRM_IOWR(0x48, drm_via_dma_init_t)
+#define DRM_IOCTL_VIA_CMDBUFFER        DRM_IOW(0x48, drm_via_cmdbuffer_t)
 #define DRM_IOCTL_VIA_FLUSH    DRM_IO(0x49)
+#define DRM_IOCTL_VIA_PCICMD   DRM_IOW(0x4A, drm_via_cmdbuffer_t)
+
 
 /* Indices into buf.Setup where various bits of state are mirrored per
  * context and per buffer.  These can be fired at the card as a unit,
@@ -200,6 +204,7 @@ int via_decoder_futex( DRM_IOCTL_ARGS );
 int via_dma_init( DRM_IOCTL_ARGS );
 int via_cmdbuffer( DRM_IOCTL_ARGS );
 int via_flush_ioctl( DRM_IOCTL_ARGS );
+int via_pci_cmdbuffer( DRM_IOCTL_ARGS );
 
 #endif
 #endif /* _VIA_DRM_H_ */
index b3119f6..8c4e748 100644 (file)
@@ -21,6 +21,7 @@
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
+
 #include <linux/config.h>
 #include "via.h"
 #include "drmP.h"
 
 #define DRIVER_NAME            "via"
 #define DRIVER_DESC            "VIA Unichrome"
-#define DRIVER_DATE            "20040819"
+#define DRIVER_DATE            "20040907"
 
 #define DRIVER_MAJOR           1
-#define DRIVER_MINOR           4
+#define DRIVER_MINOR           5
 #define DRIVER_PATCHLEVEL      0
 
 
@@ -47,7 +48,8 @@
         [DRM_IOCTL_NR(DRM_IOCTL_VIA_DEC_FUTEX)] = { via_decoder_futex, 1, 0}, \
         [DRM_IOCTL_NR(DRM_IOCTL_VIA_DMA_INIT)] = { via_dma_init, 1, 0}, \
         [DRM_IOCTL_NR(DRM_IOCTL_VIA_CMDBUFFER)] = { via_cmdbuffer, 1, 0}, \
-        [DRM_IOCTL_NR(DRM_IOCTL_VIA_FLUSH)] = { via_flush_ioctl, 1, 0}
+       [DRM_IOCTL_NR(DRM_IOCTL_VIA_FLUSH)] = { via_flush_ioctl, 1, 0}, \
+        [DRM_IOCTL_NR(DRM_IOCTL_VIA_PCICMD)] = { via_pci_cmdbuffer, 1, 0}
 
 
 #define __HAVE_COUNTERS                0
index dd4a370..39ccf0b 100644 (file)
@@ -46,6 +46,7 @@ typedef struct drm_via_private {
         uint32_t * last_pause_ptr;
         volatile uint32_t * hw_addr_ptr;
         drm_via_ring_buffer_t ring;
+       char pci_buf[VIA_PREALLOCATED_PCI_SIZE];
 } drm_via_private_t;