diff options
Diffstat (limited to 'shared-core/via_dma.c')
-rw-r--r-- | shared-core/via_dma.c | 74 |
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; } |