📄 gamma_drv.c
字号:
sizeof(*dev->queuelist[0]), DRM_MEM_QUEUES); dev->queuelist[i] = NULL; } } drm_free(dev->queuelist, dev->queue_slots * sizeof(*dev->queuelist), DRM_MEM_QUEUES); dev->queuelist = NULL; } drm_dma_takedown(dev); dev->queue_count = 0; if (dev->lock.hw_lock) { dev->lock.hw_lock = NULL; /* SHM removed */ dev->lock.pid = 0; wake_up_interruptible(&dev->lock.lock_queue); } up(&dev->struct_sem); return 0;}int gamma_found(void){ return devices;}int gamma_find_devices(void){ struct pci_dev *d = NULL, *one = NULL, *two = NULL; d = pci_find_device(PCI_VENDOR_ID_3DLABS,PCI_DEVICE_ID_3DLABS_GAMMA,d); if (!d) return 0; one = pci_find_device(PCI_VENDOR_ID_3DLABS,PCI_DEVICE_ID_3DLABS_MX,d); if (!one) return 0; /* Make sure it's on the same card, if not - no MX's found */ if (PCI_SLOT(d->devfn) != PCI_SLOT(one->devfn)) return 0; two = pci_find_device(PCI_VENDOR_ID_3DLABS,PCI_DEVICE_ID_3DLABS_MX,one); if (!two) return 1; /* Make sure it's on the same card, if not - only 1 MX found */ if (PCI_SLOT(d->devfn) != PCI_SLOT(two->devfn)) return 1; /* Two MX's found - we don't currently support more than 2 */ return 2;}/* gamma_init is called via init_module at module load time, or via * linux/init/main.c (this is not currently supported). */static int __init gamma_init(void){ int retcode; drm_device_t *dev = &gamma_device; DRM_DEBUG("\n"); memset((void *)dev, 0, sizeof(*dev)); dev->count_lock = SPIN_LOCK_UNLOCKED; sema_init(&dev->struct_sem, 1);#ifdef MODULE drm_parse_options(gamma);#endif devices = gamma_find_devices(); if (devices == 0) return -1; if ((retcode = misc_register(&gamma_misc))) { DRM_ERROR("Cannot register \"%s\"\n", GAMMA_NAME); return retcode; } dev->device = MKDEV(MISC_MAJOR, gamma_misc.minor); dev->name = GAMMA_NAME; drm_mem_init(); drm_proc_init(dev); DRM_INFO("Initialized %s %d.%d.%d %s on minor %d with %d MX devices\n", GAMMA_NAME, GAMMA_MAJOR, GAMMA_MINOR, GAMMA_PATCHLEVEL, GAMMA_DATE, gamma_misc.minor, devices); return 0;}/* gamma_cleanup is called via cleanup_module at module unload time. */static void __exit gamma_cleanup(void){ drm_device_t *dev = &gamma_device; DRM_DEBUG("\n"); drm_proc_cleanup(); if (misc_deregister(&gamma_misc)) { DRM_ERROR("Cannot unload module\n"); } else { DRM_INFO("Module unloaded\n"); } gamma_takedown(dev);}module_init(gamma_init);module_exit(gamma_cleanup);int gamma_version(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ drm_version_t version; int len; if (copy_from_user(&version, (drm_version_t *)arg, sizeof(version))) return -EFAULT;#define DRM_COPY(name,value) \ len = strlen(value); \ if (len > name##_len) len = name##_len; \ name##_len = strlen(value); \ if (len && name) { \ if (copy_to_user(name, value, len)) \ return -EFAULT; \ } version.version_major = GAMMA_MAJOR; version.version_minor = GAMMA_MINOR; version.version_patchlevel = GAMMA_PATCHLEVEL; DRM_COPY(version.name, GAMMA_NAME); DRM_COPY(version.date, GAMMA_DATE); DRM_COPY(version.desc, GAMMA_DESC); if (copy_to_user((drm_version_t *)arg, &version, sizeof(version))) return -EFAULT; return 0;}int gamma_open(struct inode *inode, struct file *filp){ drm_device_t *dev = &gamma_device; int retcode = 0; DRM_DEBUG("open_count = %d\n", dev->open_count); if (!(retcode = drm_open_helper(inode, filp, dev))) {#if LINUX_VERSION_CODE < 0x020333 MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */#endif atomic_inc(&dev->total_open); spin_lock(&dev->count_lock); if (!dev->open_count++) { spin_unlock(&dev->count_lock); return gamma_setup(dev); } spin_unlock(&dev->count_lock); } return retcode;}int gamma_release(struct inode *inode, struct file *filp){ drm_file_t *priv = filp->private_data; drm_device_t *dev; int retcode = 0; lock_kernel(); dev = priv->dev; DRM_DEBUG("open_count = %d\n", dev->open_count); if (!(retcode = drm_release(inode, filp))) {#if LINUX_VERSION_CODE < 0x020333 MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */#endif atomic_inc(&dev->total_close); spin_lock(&dev->count_lock); if (!--dev->open_count) { if (atomic_read(&dev->ioctl_count) || dev->blocked) { DRM_ERROR("Device busy: %d %d\n", atomic_read(&dev->ioctl_count), dev->blocked); spin_unlock(&dev->count_lock); unlock_kernel(); return -EBUSY; } spin_unlock(&dev->count_lock); unlock_kernel(); return gamma_takedown(dev); } spin_unlock(&dev->count_lock); } unlock_kernel(); return retcode;}/* drm_ioctl is called whenever a process performs an ioctl on /dev/drm. */int gamma_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ int nr = DRM_IOCTL_NR(cmd); drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; int retcode = 0; drm_ioctl_desc_t *ioctl; drm_ioctl_t *func; atomic_inc(&dev->ioctl_count); atomic_inc(&dev->total_ioctl); ++priv->ioctl_count; DRM_DEBUG("pid = %d, cmd = 0x%02x, nr = 0x%02x, dev 0x%x, auth = %d\n", current->pid, cmd, nr, dev->device, priv->authenticated); if (nr >= GAMMA_IOCTL_COUNT) { retcode = -EINVAL; } else { ioctl = &gamma_ioctls[nr]; func = ioctl->func; if (!func) { DRM_DEBUG("no function\n"); retcode = -EINVAL; } else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN)) || (ioctl->auth_needed && !priv->authenticated)) { retcode = -EACCES; } else { retcode = (func)(inode, filp, cmd, arg); } } atomic_dec(&dev->ioctl_count); return retcode;}int gamma_unlock(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_lock_t lock; if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock))) return -EFAULT; if (lock.context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", current->pid, lock.context); return -EINVAL; } DRM_DEBUG("%d frees lock (%d holds)\n", lock.context, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); atomic_inc(&dev->total_unlocks); if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock)) atomic_inc(&dev->total_contends); drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT); gamma_dma_schedule(dev, 1); if (!dev->context_flag) { if (drm_lock_free(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) { DRM_ERROR("\n"); } }#if DRM_DMA_HISTOGRAM atomic_inc(&dev->histo.lhld[drm_histogram_slot(get_cycles() - dev->lck_start)]);#endif unblock_all_signals(); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -