⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 drm_bufs.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	int byte_count;	int i;	drm_buf_t **temp_buflist;	if (!dma)		return -EINVAL;	count = request->count;	order = drm_order(request->size);	size = 1 << order;	alignment = (request->flags & _DRM_PAGE_ALIGN)	    ? PAGE_ALIGN(size) : size;	page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;	total = PAGE_SIZE << page_order;	byte_count = 0;	agp_offset = dev->agp->base + request->agp_start;	DRM_DEBUG("count:      %d\n", count);	DRM_DEBUG("order:      %d\n", order);	DRM_DEBUG("size:       %d\n", size);	DRM_DEBUG("agp_offset: %lu\n", agp_offset);	DRM_DEBUG("alignment:  %d\n", alignment);	DRM_DEBUG("page_order: %d\n", page_order);	DRM_DEBUG("total:      %d\n", total);	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)		return -EINVAL;	if (dev->queue_count)		return -EBUSY;	/* Not while in use */	spin_lock(&dev->count_lock);	if (dev->buf_use) {		spin_unlock(&dev->count_lock);		return -EBUSY;	}	atomic_inc(&dev->buf_alloc);	spin_unlock(&dev->count_lock);	down(&dev->struct_sem);	entry = &dma->bufs[order];	if (entry->buf_count) {		up(&dev->struct_sem);		atomic_dec(&dev->buf_alloc);		return -ENOMEM;	/* May only call once for each order */	}	if (count < 0 || count > 4096) {		up(&dev->struct_sem);		atomic_dec(&dev->buf_alloc);		return -EINVAL;	}	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),				   DRM_MEM_BUFS);	if (!entry->buflist) {		up(&dev->struct_sem);		atomic_dec(&dev->buf_alloc);		return -ENOMEM;	}	memset(entry->buflist, 0, count * sizeof(*entry->buflist));	entry->buf_size = size;	entry->page_order = page_order;	offset = 0;	while (entry->buf_count < 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 + offset);		buf->bus_address = agp_offset + offset;		buf->address = (void *)(agp_offset + offset);		buf->next = NULL;		buf->waiting = 0;		buf->pending = 0;		init_waitqueue_head(&buf->dma_wait);		buf->filp = NULL;		buf->dev_priv_size = dev->driver->dev_priv_size;		buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);		if (!buf->dev_private) {			/* Set count correctly so we free the proper amount. */			entry->buf_count = count;			drm_cleanup_buf_error(dev, entry);			up(&dev->struct_sem);			atomic_dec(&dev->buf_alloc);			return -ENOMEM;		}		memset(buf->dev_private, 0, buf->dev_priv_size);		DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);		offset += alignment;		entry->buf_count++;		byte_count += PAGE_SIZE << page_order;	}	DRM_DEBUG("byte_count: %d\n", byte_count);	temp_buflist = drm_realloc(dma->buflist,				   dma->buf_count * sizeof(*dma->buflist),				   (dma->buf_count + entry->buf_count)				   * sizeof(*dma->buflist), DRM_MEM_BUFS);	if (!temp_buflist) {		/* Free the entry because it isn't valid */		drm_cleanup_buf_error(dev, entry);		up(&dev->struct_sem);		atomic_dec(&dev->buf_alloc);		return -ENOMEM;	}	dma->buflist = temp_buflist;	for (i = 0; i < entry->buf_count; i++) {		dma->buflist[i + dma->buf_count] = &entry->buflist[i];	}	dma->buf_count += entry->buf_count;	dma->byte_count += byte_count;	DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);	DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);	up(&dev->struct_sem);	request->count = entry->buf_count;	request->size = size;	dma->flags = _DRM_DMA_USE_AGP;	atomic_dec(&dev->buf_alloc);	return 0;}EXPORT_SYMBOL(drm_addbufs_agp);#endif				/* __OS_HAS_AGP */int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request){	drm_device_dma_t *dma = dev->dma;	int count;	int order;	int size;	int total;	int page_order;	drm_buf_entry_t *entry;	unsigned long page;	drm_buf_t *buf;	int alignment;	unsigned long offset;	int i;	int byte_count;	int page_count;	unsigned long *temp_pagelist;	drm_buf_t **temp_buflist;	if (!drm_core_check_feature(dev, DRIVER_PCI_DMA))		return -EINVAL;	if (!dma)		return -EINVAL;	count = request->count;	order = drm_order(request->size);	size = 1 << order;	DRM_DEBUG("count=%d, size=%d (%d), order=%d, queue_count=%d\n",		  request->count, request->size, size, order, dev->queue_count);	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)		return -EINVAL;	if (dev->queue_count)		return -EBUSY;	/* Not while in use */	alignment = (request->flags & _DRM_PAGE_ALIGN)	    ? PAGE_ALIGN(size) : size;	page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;	total = PAGE_SIZE << page_order;	spin_lock(&dev->count_lock);	if (dev->buf_use) {		spin_unlock(&dev->count_lock);		return -EBUSY;	}	atomic_inc(&dev->buf_alloc);	spin_unlock(&dev->count_lock);	down(&dev->struct_sem);	entry = &dma->bufs[order];	if (entry->buf_count) {		up(&dev->struct_sem);		atomic_dec(&dev->buf_alloc);		return -ENOMEM;	/* May only call once for each order */	}	if (count < 0 || count > 4096) {		up(&dev->struct_sem);		atomic_dec(&dev->buf_alloc);		return -EINVAL;	}	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),				   DRM_MEM_BUFS);	if (!entry->buflist) {		up(&dev->struct_sem);		atomic_dec(&dev->buf_alloc);		return -ENOMEM;	}	memset(entry->buflist, 0, count * sizeof(*entry->buflist));	entry->seglist = drm_alloc(count * sizeof(*entry->seglist),				   DRM_MEM_SEGS);	if (!entry->seglist) {		drm_free(entry->buflist,			 count * sizeof(*entry->buflist), DRM_MEM_BUFS);		up(&dev->struct_sem);		atomic_dec(&dev->buf_alloc);		return -ENOMEM;	}	memset(entry->seglist, 0, count * sizeof(*entry->seglist));	/* Keep the original pagelist until we know all the allocations	 * have succeeded	 */	temp_pagelist = drm_alloc((dma->page_count + (count << page_order))				  * sizeof(*dma->pagelist), DRM_MEM_PAGES);	if (!temp_pagelist) {		drm_free(entry->buflist,			 count * sizeof(*entry->buflist), DRM_MEM_BUFS);		drm_free(entry->seglist,			 count * sizeof(*entry->seglist), DRM_MEM_SEGS);		up(&dev->struct_sem);		atomic_dec(&dev->buf_alloc);		return -ENOMEM;	}	memcpy(temp_pagelist,	       dma->pagelist, dma->page_count * sizeof(*dma->pagelist));	DRM_DEBUG("pagelist: %d entries\n",		  dma->page_count + (count << page_order));	entry->buf_size = size;	entry->page_order = page_order;	byte_count = 0;	page_count = 0;	while (entry->buf_count < count) {		page = drm_alloc_pages(page_order, DRM_MEM_DMA);		if (!page) {			/* Set count correctly so we free the proper amount. */			entry->buf_count = count;			entry->seg_count = count;			drm_cleanup_buf_error(dev, entry);			drm_free(temp_pagelist,				 (dma->page_count + (count << page_order))				 * sizeof(*dma->pagelist), DRM_MEM_PAGES);			up(&dev->struct_sem);			atomic_dec(&dev->buf_alloc);			return -ENOMEM;		}		entry->seglist[entry->seg_count++] = page;		for (i = 0; i < (1 << page_order); i++) {			DRM_DEBUG("page %d @ 0x%08lx\n",				  dma->page_count + page_count,				  page + PAGE_SIZE * i);			temp_pagelist[dma->page_count + page_count++]			    = page + PAGE_SIZE * i;		}		for (offset = 0;		     offset + size <= total && entry->buf_count < count;		     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->filp = NULL;			buf->dev_priv_size = dev->driver->dev_priv_size;			buf->dev_private = drm_alloc(buf->dev_priv_size,						     DRM_MEM_BUFS);			if (!buf->dev_private) {				/* Set count correctly so we free the proper amount. */				entry->buf_count = count;				entry->seg_count = count;				drm_cleanup_buf_error(dev, entry);				drm_free(temp_pagelist,					 (dma->page_count +					  (count << page_order))					 * sizeof(*dma->pagelist),					 DRM_MEM_PAGES);				up(&dev->struct_sem);				atomic_dec(&dev->buf_alloc);				return -ENOMEM;			}			memset(buf->dev_private, 0, buf->dev_priv_size);			DRM_DEBUG("buffer %d @ %p\n",				  entry->buf_count, buf->address);		}		byte_count += PAGE_SIZE << page_order;	}	temp_buflist = drm_realloc(dma->buflist,				   dma->buf_count * sizeof(*dma->buflist),				   (dma->buf_count + entry->buf_count)				   * sizeof(*dma->buflist), DRM_MEM_BUFS);	if (!temp_buflist) {		/* Free the entry because it isn't valid */		drm_cleanup_buf_error(dev, entry);		drm_free(temp_pagelist,			 (dma->page_count + (count << page_order))			 * sizeof(*dma->pagelist), DRM_MEM_PAGES);		up(&dev->struct_sem);		atomic_dec(&dev->buf_alloc);		return -ENOMEM;	}	dma->buflist = temp_buflist;	for (i = 0; i < entry->buf_count; i++) {		dma->buflist[i + dma->buf_count] = &entry->buflist[i];	}	/* No allocations failed, so now we can replace the orginal pagelist	 * with the new one.	 */	if (dma->page_count) {		drm_free(dma->pagelist,			 dma->page_count * sizeof(*dma->pagelist),			 DRM_MEM_PAGES);	}	dma->pagelist = temp_pagelist;	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);	up(&dev->struct_sem);	request->count = entry->buf_count;	request->size = size;	atomic_dec(&dev->buf_alloc);	return 0;}EXPORT_SYMBOL(drm_addbufs_pci);static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request){	drm_device_dma_t *dma = dev->dma;	drm_buf_entry_t *entry;	drm_buf_t *buf;	unsigned long offset;	unsigned long agp_offset;	int count;	int order;	int size;	int alignment;	int page_order;	int total;	int byte_count;	int i;	drm_buf_t **temp_buflist;	if (!drm_core_check_feature(dev, DRIVER_SG))		return -EINVAL;	if (!dma)		return -EINVAL;	count = request->count;	order = drm_order(request->size);	size = 1 << order;	alignment = (request->flags & _DRM_PAGE_ALIGN)	    ? PAGE_ALIGN(size) : size;	page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;	total = PAGE_SIZE << page_order;	byte_count = 0;	agp_offset = request->agp_start;	DRM_DEBUG("count:      %d\n", count);	DRM_DEBUG("order:      %d\n", order);	DRM_DEBUG("size:       %d\n", size);	DRM_DEBUG("agp_offset: %lu\n", agp_offset);	DRM_DEBUG("alignment:  %d\n", alignment);	DRM_DEBUG("page_order: %d\n", page_order);	DRM_DEBUG("total:      %d\n", total);	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)		return -EINVAL;	if (dev->queue_count)		return -EBUSY;	/* Not while in use */	spin_lock(&dev->count_lock);	if (dev->buf_use) {		spin_unlock(&dev->count_lock);		return -EBUSY;	}	atomic_inc(&dev->buf_alloc);	spin_unlock(&dev->count_lock);	down(&dev->struct_sem);	entry = &dma->bufs[order];	if (entry->buf_count) {		up(&dev->struct_sem);		atomic_dec(&dev->buf_alloc);		return -ENOMEM;	/* May only call once for each order */	}	if (count < 0 || count > 4096) {		up(&dev->struct_sem);		atomic_dec(&dev->buf_alloc);		return -EINVAL;	}	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),				   DRM_MEM_BUFS);	if (!entry->buflist) {		up(&dev->struct_sem);		atomic_dec(&dev->buf_alloc);		return -ENOMEM;	}	memset(entry->buflist, 0, count * sizeof(*entry->buflist));	entry->buf_size = size;	entry->page_order = page_order;	offset = 0;	while (entry->buf_count < 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 + offset);		buf->bus_address = agp_offset + offset;		buf->address = (void *)(agp_offset + offset					+ (unsigned long)dev->sg->virtual);		buf->next = NULL;		buf->waiting = 0;		buf->pending = 0;		init_waitqueue_head(&buf->dma_wait);		buf->filp = NULL;		buf->dev_priv_size = dev->driver->dev_priv_size;		buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);		if (!buf->dev_private) {			/* Set count correctly so we free the proper amount. */			entry->buf_count = count;			drm_cleanup_buf_error(dev, entry);			up(&dev->struct_sem);			atomic_dec(&dev->buf_alloc);			return -ENOMEM;		}		memset(buf->dev_private, 0, buf->dev_priv_size);		DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);		offset += alignment;		entry->buf_count++;		byte_count += PAGE_SIZE << page_order;	}	DRM_DEBUG("byte_count: %d\n", byte_count);	temp_buflist = drm_realloc(dma->buflist,				   dma->buf_count * sizeof(*dma->buflist),				   (dma->buf_count + entry->buf_count)				   * sizeof(*dma->buflist), DRM_MEM_BUFS);	if (!temp_buflist) {		/* Free the entry because it isn't valid */		drm_cleanup_buf_error(dev, entry);		up(&dev->struct_sem);		atomic_dec(&dev->buf_alloc);		return -ENOMEM;	}	dma->buflist = temp_buflist;	for (i = 0; i < entry->buf_count; i++) {		dma->buflist[i + dma->buf_count] = &entry->buflist[i];	}	dma->buf_count += entry->buf_count;	dma->byte_count += byte_count;	DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);	DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);	up(&dev->struct_sem);	request->count = entry->buf_count;	request->size = size;	dma->flags = _DRM_DMA_USE_SG;	atomic_dec(&dev->buf_alloc);	return 0;}static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request){	drm_device_dma_t *dma = dev->dma;	drm_buf_entry_t *entry;	drm_buf_t *buf;	unsigned long offset;	unsigned long agp_offset;	int count;	int order;	int size;	int alignment;	int page_order;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -