r128_cce.c
来自「linux 内核源代码」· C语言 代码 · 共 935 行 · 第 1/2 页
C
935 行
DRM_ERROR("could not find mmio region!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); return -EINVAL; } dev_priv->cce_ring = drm_core_findmap(dev, init->ring_offset); if (!dev_priv->cce_ring) { DRM_ERROR("could not find cce ring region!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); return -EINVAL; } dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset); if (!dev_priv->ring_rptr) { DRM_ERROR("could not find ring read pointer!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); return -EINVAL; } dev->agp_buffer_token = init->buffers_offset; dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); if (!dev->agp_buffer_map) { DRM_ERROR("could not find dma buffer region!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); return -EINVAL; } if (!dev_priv->is_pci) { dev_priv->agp_textures = drm_core_findmap(dev, init->agp_textures_offset); if (!dev_priv->agp_textures) { DRM_ERROR("could not find agp texture region!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); return -EINVAL; } } dev_priv->sarea_priv = (drm_r128_sarea_t *) ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);#if __OS_HAS_AGP if (!dev_priv->is_pci) { drm_core_ioremap(dev_priv->cce_ring, dev); drm_core_ioremap(dev_priv->ring_rptr, dev); drm_core_ioremap(dev->agp_buffer_map, dev); if (!dev_priv->cce_ring->handle || !dev_priv->ring_rptr->handle || !dev->agp_buffer_map->handle) { DRM_ERROR("Could not ioremap agp regions!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); return -ENOMEM; } } else#endif { dev_priv->cce_ring->handle = (void *)dev_priv->cce_ring->offset; dev_priv->ring_rptr->handle = (void *)dev_priv->ring_rptr->offset; dev->agp_buffer_map->handle = (void *)dev->agp_buffer_map->offset; }#if __OS_HAS_AGP if (!dev_priv->is_pci) dev_priv->cce_buffers_offset = dev->agp->base; else#endif dev_priv->cce_buffers_offset = (unsigned long)dev->sg->virtual; dev_priv->ring.start = (u32 *) dev_priv->cce_ring->handle; dev_priv->ring.end = ((u32 *) dev_priv->cce_ring->handle + init->ring_size / sizeof(u32)); dev_priv->ring.size = init->ring_size; dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8); dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1; dev_priv->ring.high_mark = 128; dev_priv->sarea_priv->last_frame = 0; R128_WRITE(R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame); dev_priv->sarea_priv->last_dispatch = 0; R128_WRITE(R128_LAST_DISPATCH_REG, dev_priv->sarea_priv->last_dispatch);#if __OS_HAS_AGP if (dev_priv->is_pci) {#endif dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE; dev_priv->gart_info.addr = NULL; dev_priv->gart_info.bus_addr = 0; dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { DRM_ERROR("failed to init PCI GART!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); return -ENOMEM; } R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr);#if __OS_HAS_AGP }#endif r128_cce_init_ring_buffer(dev, dev_priv); r128_cce_load_microcode(dev_priv); dev->dev_private = (void *)dev_priv; r128_do_engine_reset(dev); return 0;}int r128_do_cleanup_cce(struct drm_device * dev){ /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. */ if (dev->irq_enabled) drm_irq_uninstall(dev); if (dev->dev_private) { drm_r128_private_t *dev_priv = dev->dev_private;#if __OS_HAS_AGP if (!dev_priv->is_pci) { if (dev_priv->cce_ring != NULL) drm_core_ioremapfree(dev_priv->cce_ring, dev); if (dev_priv->ring_rptr != NULL) drm_core_ioremapfree(dev_priv->ring_rptr, dev); if (dev->agp_buffer_map != NULL) { drm_core_ioremapfree(dev->agp_buffer_map, dev); dev->agp_buffer_map = NULL; } } else#endif { if (dev_priv->gart_info.bus_addr) if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info)) DRM_ERROR ("failed to cleanup PCI GART!\n"); } drm_free(dev->dev_private, sizeof(drm_r128_private_t), DRM_MEM_DRIVER); dev->dev_private = NULL; } return 0;}int r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv){ drm_r128_init_t *init = data; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, file_priv); switch (init->func) { case R128_INIT_CCE: return r128_do_init_cce(dev, init); case R128_CLEANUP_CCE: return r128_do_cleanup_cce(dev); } return -EINVAL;}int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv){ drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, file_priv); if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) { DRM_DEBUG("%s while CCE running\n", __FUNCTION__); return 0; } r128_do_cce_start(dev_priv); return 0;}/* Stop the CCE. The engine must have been idled before calling this * routine. */int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv){ drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_cce_stop_t *stop = data; int ret; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, file_priv); /* Flush any pending CCE commands. This ensures any outstanding * commands are exectuted by the engine before we turn it off. */ if (stop->flush) { r128_do_cce_flush(dev_priv); } /* If we fail to make the engine go idle, we return an error * code so that the DRM ioctl wrapper can try again. */ if (stop->idle) { ret = r128_do_cce_idle(dev_priv); if (ret) return ret; } /* Finally, we can turn off the CCE. If the engine isn't idle, * we will get some dropped triangles as they won't be fully * rendered before the CCE is shut down. */ r128_do_cce_stop(dev_priv); /* Reset the engine */ r128_do_engine_reset(dev); return 0;}/* Just reset the CCE ring. Called as part of an X Server engine reset. */int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_priv){ drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { DRM_DEBUG("%s called before init done\n", __FUNCTION__); return -EINVAL; } r128_do_cce_reset(dev_priv); /* The CCE is no longer running after an engine reset */ dev_priv->cce_running = 0; return 0;}int r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv){ drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, file_priv); if (dev_priv->cce_running) { r128_do_cce_flush(dev_priv); } return r128_do_cce_idle(dev_priv);}int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv){ DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, file_priv); return r128_do_engine_reset(dev);}int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv){ return -EINVAL;}/* ================================================================ * Freelist management */#define R128_BUFFER_USED 0xffffffff#define R128_BUFFER_FREE 0#if 0static int r128_freelist_init(struct drm_device * dev){ struct drm_device_dma *dma = dev->dma; drm_r128_private_t *dev_priv = dev->dev_private; struct drm_buf *buf; drm_r128_buf_priv_t *buf_priv; drm_r128_freelist_t *entry; int i; dev_priv->head = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER); if (dev_priv->head == NULL) return -ENOMEM; memset(dev_priv->head, 0, sizeof(drm_r128_freelist_t)); dev_priv->head->age = R128_BUFFER_USED; for (i = 0; i < dma->buf_count; i++) { buf = dma->buflist[i]; buf_priv = buf->dev_private; entry = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER); if (!entry) return -ENOMEM; entry->age = R128_BUFFER_FREE; entry->buf = buf; entry->prev = dev_priv->head; entry->next = dev_priv->head->next; if (!entry->next) dev_priv->tail = entry; buf_priv->discard = 0; buf_priv->dispatched = 0; buf_priv->list_entry = entry; dev_priv->head->next = entry; if (dev_priv->head->next) dev_priv->head->next->prev = entry; } return 0;}#endifstatic struct drm_buf *r128_freelist_get(struct drm_device * dev){ struct drm_device_dma *dma = dev->dma; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_buf_priv_t *buf_priv; struct drm_buf *buf; int i, t; /* FIXME: Optimize -- use freelist code */ for (i = 0; i < dma->buf_count; i++) { buf = dma->buflist[i]; buf_priv = buf->dev_private; if (buf->file_priv == 0) return buf; } for (t = 0; t < dev_priv->usec_timeout; t++) { u32 done_age = R128_READ(R128_LAST_DISPATCH_REG); for (i = 0; i < dma->buf_count; i++) { buf = dma->buflist[i]; buf_priv = buf->dev_private; if (buf->pending && buf_priv->age <= done_age) { /* The buffer has been processed, so it * can now be used. */ buf->pending = 0; return buf; } } DRM_UDELAY(1); } DRM_DEBUG("returning NULL!\n"); return NULL;}void r128_freelist_reset(struct drm_device * dev){ struct drm_device_dma *dma = dev->dma; int i; for (i = 0; i < dma->buf_count; i++) { struct drm_buf *buf = dma->buflist[i]; drm_r128_buf_priv_t *buf_priv = buf->dev_private; buf_priv->age = 0; }}/* ================================================================ * CCE command submission */int r128_wait_ring(drm_r128_private_t * dev_priv, int n){ drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i; for (i = 0; i < dev_priv->usec_timeout; i++) { r128_update_ring_snapshot(dev_priv); if (ring->space >= n) return 0; DRM_UDELAY(1); } /* FIXME: This is being ignored... */ DRM_ERROR("failed!\n"); return -EBUSY;}static int r128_cce_get_buffers(struct drm_device * dev, struct drm_file *file_priv, struct drm_dma * d){ int i; struct drm_buf *buf; for (i = d->granted_count; i < d->request_count; i++) { buf = r128_freelist_get(dev); if (!buf) return -EAGAIN; buf->file_priv = file_priv; if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) return -EFAULT; if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, sizeof(buf->total))) return -EFAULT; d->granted_count++; } return 0;}int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv){ struct drm_device_dma *dma = dev->dma; int ret = 0; struct drm_dma *d = data; LOCK_TEST_WITH_RETURN(dev, file_priv); /* Please don't send us buffers. */ if (d->send_count != 0) { DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", DRM_CURRENTPID, d->send_count); return -EINVAL; } /* We'll send you buffers. */ if (d->request_count < 0 || d->request_count > dma->buf_count) { DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", DRM_CURRENTPID, d->request_count, dma->buf_count); return -EINVAL; } d->granted_count = 0; if (d->request_count) { ret = r128_cce_get_buffers(dev, file_priv, d); } return ret;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?