summaryrefslogtreecommitdiff
path: root/shared-core/via_dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'shared-core/via_dma.c')
-rw-r--r--shared-core/via_dma.c74
1 files changed, 42 insertions, 32 deletions
diff --git a/shared-core/via_dma.c b/shared-core/via_dma.c
index ee4a02ab..179636ea 100644
--- a/shared-core/via_dma.c
+++ b/shared-core/via_dma.c
@@ -26,7 +26,11 @@
*vb++ = (w2); \
dev_priv->dma_low += 8;
-
+#define PCI_BUF_SIZE 1024000
+
+static char pci_buf[PCI_BUF_SIZE];
+static unsigned long pci_bufsiz = PCI_BUF_SIZE;
+
static void via_cmdbuf_start(drm_via_private_t * dev_priv);
static void via_cmdbuf_pause(drm_via_private_t * dev_priv);
@@ -203,6 +207,9 @@ int via_dma_init(DRM_IOCTL_ARGS)
case VIA_CLEANUP_DMA:
retcode = via_dma_cleanup(dev);
break;
+ case VIA_DMA_INITIALIZED:
+ retcode = (dev_priv->ring.virtual_start != NULL) ? 0: DRM_ERR( EFAULT );
+ break;
default:
retcode = DRM_ERR(EINVAL);
break;
@@ -278,52 +285,55 @@ 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;
+ const uint32_t *regend = regbuf + (size >> 2);
int ret;
+ int check_2d_cmd = 1;
if ((ret = via_check_command_stream(regbuf, size)))
return ret;
- size >>= 3;
- for (i = 0; i < size; ++i) {
- offset = (*regbuf++ & ~HALCYON_HEADER1) << 2;
- value = *regbuf++;
- VIA_WRITE(offset, value);
- }
+ while (regbuf != regend) {
+ if ( *regbuf == HALCYON_HEADER2 ) {
+
+ regbuf++;
+ check_2d_cmd = ( *regbuf != HALCYON_SUB_ADDR0 );
+ VIA_WRITE(HC_REG_TRANS_SET + HC_REG_BASE, *regbuf++);
+
+ } else if ( check_2d_cmd && ((*regbuf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 )) {
+
+ register uint32_t addr = ( (*regbuf++ ) & ~HALCYON_HEADER1MASK) << 2;
+ VIA_WRITE( addr, *regbuf++ );
+
+ } else if ( ( *regbuf & HALCYON_FIREMASK ) == HALCYON_FIRECMD ) {
+
+ VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE, *regbuf++);
+ if ( ( regbuf != regend ) &&
+ ((*regbuf & HALCYON_FIREMASK) == HALCYON_FIRECMD))
+ regbuf++;
+ if (( *regbuf & HALCYON_CMDBMASK ) != HC_ACMD_HCmdB )
+ check_2d_cmd = 1;
+ } else {
+
+ VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE , *regbuf++);
+
+ }
+ }
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) {
+ if (cmd->size > pci_bufsiz && pci_bufsiz > 0) {
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);
- if (DRM_COPY_FROM_USER(hugebuf, cmd->buf, cmd->size))
- return DRM_ERR(EFAULT);
- ret = via_parse_pci_cmdbuffer(dev, hugebuf, cmd->size);
- kfree(hugebuf);
- } else {
- if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
- return DRM_ERR(EFAULT);
- ret =
- via_parse_pci_cmdbuffer(dev, dev_priv->pci_buf, cmd->size);
- }
+ }
+ if (DRM_COPY_FROM_USER(pci_buf, cmd->buf, cmd->size))
+ return DRM_ERR(EFAULT);
+ ret = via_parse_pci_cmdbuffer(dev, pci_buf, cmd->size);
return ret;
}