Esempio n. 1
0
/**
 * Initialize the AGP resources.
 *
 * \return pointer to a drm_agp_head structure.
 *
 */
drm_agp_head_t *drm_agp_init(drm_device_t *dev)
{
	drm_agp_head_t *head         = NULL;

	if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
		return NULL;
	memset((void *)head, 0, sizeof(*head));
	head->bridge = agp_find_bridge(dev->pdev);
	if (!head->bridge) {
		if (!(head->bridge = agp_backend_acquire(dev->pdev))) {
			drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
			return NULL;
		}
		agp_copy_info(head->bridge, &head->agp_info);
		agp_backend_release(head->bridge);
	} else {
		agp_copy_info(head->bridge, &head->agp_info);
	}
	if (head->agp_info.chipset == NOT_SUPPORTED) {
		drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
		return NULL;
	}
	head->memory = NULL;
	head->cant_use_aperture = head->agp_info.cant_use_aperture;
	head->page_mask = head->agp_info.page_mask;

	return head;
}
Esempio n. 2
0
static int compat_agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
{
	struct agp_info32 userinfo;
	struct agp_kern_info kerninfo;

	agp_copy_info(agp_bridge, &kerninfo);

	userinfo.version.major = kerninfo.version.major;
	userinfo.version.minor = kerninfo.version.minor;
	userinfo.bridge_id = kerninfo.device->vendor |
	    (kerninfo.device->device << 16);
	userinfo.agp_mode = kerninfo.mode;
	userinfo.aper_base = (compat_long_t)kerninfo.aper_base;
	userinfo.aper_size = kerninfo.aper_size;
	userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory;
	userinfo.pg_used = kerninfo.current_memory;

	if (copy_to_user(arg, &userinfo, sizeof(userinfo)))
		return -EFAULT;

	return 0;
}
static int agpioc_info_wrap(agp_file_private * priv, unsigned long arg)
{
	agp_info userinfo;
	agp_kern_info kerninfo;

	agp_copy_info(&kerninfo);

	userinfo.version.major = kerninfo.version.major;
	userinfo.version.minor = kerninfo.version.minor;
	userinfo.bridge_id = kerninfo.device->vendor |
	    (kerninfo.device->device << 16);
	userinfo.agp_mode = kerninfo.mode;
	userinfo.aper_base = kerninfo.aper_base;
	userinfo.aper_size = kerninfo.aper_size;
	userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory;
	userinfo.pg_used = kerninfo.current_memory;

	if (copy_to_user((void *) arg, &userinfo, sizeof(agp_info))) {
		return -EFAULT;
	}
	return 0;
}
static int agp_mmap(struct file *file, struct vm_area_struct *vma)
{
	unsigned int size, current_size;
	unsigned long offset;
	struct agp_client *client;
	struct agp_file_private *priv = file->private_data;
	struct agp_kern_info kerninfo;

	down(&(agp_fe.agp_mutex));

	if (agp_fe.backend_acquired != TRUE)
		goto out_eperm;

	if (!(test_bit(AGP_FF_IS_VALID, &priv->access_flags)))
		goto out_eperm;

	agp_copy_info(&kerninfo);
	size = vma->vm_end - vma->vm_start;
	current_size = kerninfo.aper_size;
	current_size = current_size * 0x100000;
	offset = vma->vm_pgoff << PAGE_SHIFT;
	DBG("%lx:%lx", offset, offset+size);

	if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) {
		if ((size + offset) > current_size)
			goto out_inval;

		client = agp_find_client_by_pid(current->pid);

		if (client == NULL)
			goto out_eperm;

		if (!agp_find_seg_in_client(client, offset, size, vma->vm_page_prot))
			goto out_inval;

		DBG("client vm_ops=%p", kerninfo.vm_ops);
		if (kerninfo.vm_ops) {
			vma->vm_ops = kerninfo.vm_ops;
		} else if (remap_page_range(vma, vma->vm_start, 
					    (kerninfo.aper_base + offset),
					    size, vma->vm_page_prot)) {
			goto out_again;
		}
		up(&(agp_fe.agp_mutex));
		return 0;
	}

	if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
		if (size != current_size)
			goto out_inval;

		DBG("controller vm_ops=%p", kerninfo.vm_ops);
		if (kerninfo.vm_ops) {
			vma->vm_ops = kerninfo.vm_ops;
		} else if (remap_page_range(vma, vma->vm_start, 
					    kerninfo.aper_base,
					    size, vma->vm_page_prot)) {
			goto out_again;
		}
		up(&(agp_fe.agp_mutex));
		return 0;
	}

out_eperm:
	up(&(agp_fe.agp_mutex));
	return -EPERM;

out_inval:
	up(&(agp_fe.agp_mutex));
	return -EINVAL;

out_again:
	up(&(agp_fe.agp_mutex));
	return -EAGAIN;
}
static int agp_mmap(struct file *file, struct vm_area_struct *vma)
{
	int size;
	int current_size;
	unsigned long offset;
	agp_client *client;
	agp_file_private *priv = (agp_file_private *) file->private_data;
	agp_kern_info kerninfo;

	lock_kernel();
	AGP_LOCK();

	if (agp_fe.backend_acquired != TRUE) {
		AGP_UNLOCK();
		unlock_kernel();
		return -EPERM;
	}
	if (!(test_bit(AGP_FF_IS_VALID, &priv->access_flags))) {
		AGP_UNLOCK();
		unlock_kernel();
		return -EPERM;
	}
	agp_copy_info(&kerninfo);
	size = vma->vm_end - vma->vm_start;
	current_size = kerninfo.aper_size;
	current_size = current_size * 0x100000;
	offset = vma->vm_pgoff << PAGE_SHIFT;

	if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) {
		if ((size + offset) > current_size) {
			AGP_UNLOCK();
			unlock_kernel();
			return -EINVAL;
		}
		client = agp_find_client_by_pid(current->pid);

		if (client == NULL) {
			AGP_UNLOCK();
			unlock_kernel();
			return -EPERM;
		}
		if (!agp_find_seg_in_client(client, offset,
					    size, vma->vm_page_prot)) {
			AGP_UNLOCK();
			unlock_kernel();
			return -EINVAL;
		}
		if (remap_page_range(vma->vm_start,
				     (kerninfo.aper_base + offset),
				     size, vma->vm_page_prot)) {
			AGP_UNLOCK();
			unlock_kernel();
			return -EAGAIN;
		}
		AGP_UNLOCK();
		unlock_kernel();
		return 0;
	}
	if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
		if (size != current_size) {
			AGP_UNLOCK();
			unlock_kernel();
			return -EINVAL;
		}
		if (remap_page_range(vma->vm_start, kerninfo.aper_base,
				     size, vma->vm_page_prot)) {
			AGP_UNLOCK();
			unlock_kernel();
			return -EAGAIN;
		}
		AGP_UNLOCK();
		unlock_kernel();
		return 0;
	}
	AGP_UNLOCK();
	unlock_kernel();
	return -EPERM;
}