summaryrefslogtreecommitdiff
path: root/shared-core/via_dma.c
diff options
context:
space:
mode:
authorThomas Hellstrom <unichrome@shipmail.org>2004-11-27 22:55:31 +0000
committerThomas Hellstrom <unichrome@shipmail.org>2004-11-27 22:55:31 +0000
commit4f8fa6028631fa1d799e9a68ed710fbc98976656 (patch)
treedf753d0e728afd97ac03388283df51f4e73a9e0d /shared-core/via_dma.c
parentf0a86288fa4d7b951f33f7b1a6ef36106c7df788 (diff)
Reworked PCI MMIO command buffer parser, and imported code from the Mesa
driver. It can now handle the 3D OpenGL commands from the Mesa unichrome driver. Added vsync frequency detection support. This will be used in the future for XvMC and better frame timing. Bumped minor version number and driver date.
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;
}