📄 mga_bufs.c
字号:
offset += alignment, ++entry->buf_count) { buf = &entry->buflist[entry->buf_count]; buf->idx = dma->buf_count + entry->buf_count; buf->total = alignment; buf->order = order; buf->used = 0; buf->offset = (dma->byte_count + byte_count + offset); buf->address = (void *)(page + offset); buf->next = NULL; buf->waiting = 0; buf->pending = 0; init_waitqueue_head(&buf->dma_wait); buf->pid = 0;#if DRM_DMA_HISTOGRAM buf->time_queued = 0; buf->time_dispatched = 0; buf->time_completed = 0; buf->time_freed = 0;#endif DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address); } byte_count += PAGE_SIZE << page_order; } dma->buflist = drm_realloc(dma->buflist, dma->buf_count * sizeof(*dma->buflist), (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist), DRM_MEM_BUFS); for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++) dma->buflist[i] = &entry->buflist[i - dma->buf_count]; dma->buf_count += entry->buf_count; dma->seg_count += entry->seg_count; dma->page_count += entry->seg_count << page_order; dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order); drm_freelist_create(&entry->freelist, entry->buf_count); for (i = 0; i < entry->buf_count; i++) { drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]); } up(&dev->struct_sem); request.count = entry->buf_count; request.size = size; if (copy_to_user((drm_buf_desc_t *)arg, &request, sizeof(request))) return -EFAULT; atomic_dec(&dev->buf_alloc); return 0;}int mga_addbufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ drm_buf_desc_t request; if (copy_from_user(&request, (drm_buf_desc_t *)arg, sizeof(request))) return -EFAULT; if(request.flags & _DRM_AGP_BUFFER) return mga_addbufs_agp(inode, filp, cmd, arg); else return mga_addbufs_pci(inode, filp, cmd, arg);}int mga_infobufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_device_dma_t *dma = dev->dma; drm_buf_info_t request; int i; int count; if (!dma) return -EINVAL; spin_lock(&dev->count_lock); if (atomic_read(&dev->buf_alloc)) { spin_unlock(&dev->count_lock); return -EBUSY; } ++dev->buf_use; /* Can't allocate more after this call */ spin_unlock(&dev->count_lock); if (copy_from_user(&request, (drm_buf_info_t *)arg, sizeof(request))) return -EFAULT; for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) { if (dma->bufs[i].buf_count) ++count; } if (request.count >= count) { for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) { if (dma->bufs[i].buf_count) { if (copy_to_user(&request.list[count].count, &dma->bufs[i].buf_count, sizeof(dma->bufs[0] .buf_count)) || copy_to_user(&request.list[count].size, &dma->bufs[i].buf_size, sizeof(dma->bufs[0].buf_size)) || copy_to_user(&request.list[count].low_mark, &dma->bufs[i] .freelist.low_mark, sizeof(dma->bufs[0] .freelist.low_mark)) || copy_to_user(&request.list[count] .high_mark, &dma->bufs[i] .freelist.high_mark, sizeof(dma->bufs[0] .freelist.high_mark))) return -EFAULT; ++count; } } } request.count = count; if (copy_to_user((drm_buf_info_t *)arg, &request, sizeof(request))) return -EFAULT; return 0;}int mga_markbufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_device_dma_t *dma = dev->dma; drm_buf_desc_t request; int order; drm_buf_entry_t *entry; if (!dma) return -EINVAL; if (copy_from_user(&request, (drm_buf_desc_t *)arg, sizeof(request))) return -EFAULT; order = drm_order(request.size); if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL; entry = &dma->bufs[order]; if (request.low_mark < 0 || request.low_mark > entry->buf_count) return -EINVAL; if (request.high_mark < 0 || request.high_mark > entry->buf_count) return -EINVAL; entry->freelist.low_mark = request.low_mark; entry->freelist.high_mark = request.high_mark; return 0;}int mga_freebufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_device_dma_t *dma = dev->dma; drm_buf_free_t request; int i; int idx; drm_buf_t *buf; if (!dma) return -EINVAL; if (copy_from_user(&request, (drm_buf_free_t *)arg, sizeof(request))) return -EFAULT; for (i = 0; i < request.count; i++) { if (copy_from_user(&idx, &request.list[i], sizeof(idx))) return -EFAULT; if (idx < 0 || idx >= dma->buf_count) { DRM_ERROR("Index %d (of %d max)\n", idx, dma->buf_count - 1); return -EINVAL; } buf = dma->buflist[idx]; if (buf->pid != current->pid) { DRM_ERROR("Process %d freeing buffer owned by %d\n", current->pid, buf->pid); return -EINVAL; } drm_free_buffer(dev, buf); } return 0;}int mga_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_device_dma_t *dma = dev->dma; int retcode = 0; const int zero = 0; unsigned long virtual; unsigned long address; drm_buf_map_t request; int i; if (!dma) return -EINVAL; spin_lock(&dev->count_lock); if (atomic_read(&dev->buf_alloc)) { spin_unlock(&dev->count_lock); return -EBUSY; } ++dev->buf_use; /* Can't allocate more after this call */ spin_unlock(&dev->count_lock); if (copy_from_user(&request, (drm_buf_map_t *)arg, sizeof(request))) return -EFAULT; if (request.count >= dma->buf_count) { if(dma->flags & _DRM_DMA_USE_AGP) { drm_mga_private_t *dev_priv = dev->dev_private; drm_map_t *map = NULL; map = dev->maplist[dev_priv->buffer_map_idx]; if (!map) { retcode = -EINVAL; goto done; } DRM_DEBUG("map->offset : %lx\n", map->offset); DRM_DEBUG("map->size : %lx\n", map->size); DRM_DEBUG("map->type : %d\n", map->type); DRM_DEBUG("map->flags : %x\n", map->flags); DRM_DEBUG("map->handle : %p\n", map->handle); DRM_DEBUG("map->mtrr : %d\n", map->mtrr); down_write(¤t->mm->mmap_sem); virtual = do_mmap(filp, 0, map->size, PROT_READ|PROT_WRITE, MAP_SHARED, (unsigned long)map->offset); up_write(¤t->mm->mmap_sem); } else { down_write(¤t->mm->mmap_sem); virtual = do_mmap(filp, 0, dma->byte_count, PROT_READ|PROT_WRITE, MAP_SHARED, 0); up_write(¤t->mm->mmap_sem); } if (virtual > -1024UL) { /* Real error */ DRM_DEBUG("mmap error\n"); retcode = (signed long)virtual; goto done; } request.virtual = (void *)virtual; for (i = 0; i < dma->buf_count; i++) { if (copy_to_user(&request.list[i].idx, &dma->buflist[i]->idx, sizeof(request.list[0].idx))) { retcode = -EFAULT; goto done; } if (copy_to_user(&request.list[i].total, &dma->buflist[i]->total, sizeof(request.list[0].total))) { retcode = -EFAULT; goto done; } if (copy_to_user(&request.list[i].used, &zero, sizeof(zero))) { retcode = -EFAULT; goto done; } address = virtual + dma->buflist[i]->offset; if (copy_to_user(&request.list[i].address, &address, sizeof(address))) { retcode = -EFAULT; goto done; } } } done: request.count = dma->buf_count; DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode); if (copy_to_user((drm_buf_map_t *)arg, &request, sizeof(request))) return -EFAULT; DRM_DEBUG("retcode : %d\n", retcode); return retcode;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -