#include <linux/debugfs.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/mount.h>
#include <linux/slab.h>
#include <linux/srcu.h>
#include <drm/drm_client.h>
#include <drm/drm_drv.h>
#include <drm/drmP.h>
#include "drm_crtc_internal.h"
#include "drm_legacy.h"
#include "drm_internal.h"
#if 0
#include "drm_crtc_internal.h"
#endif
#ifdef __DragonFly__
#if DRM_DEBUG_DEFAULT_ON == 1
#define DRM_DEBUGBITS_ON (DRM_UT_CORE | DRM_UT_DRIVER | DRM_UT_KMS | \
DRM_UT_PRIME| DRM_UT_ATOMIC | DRM_UT_FIOCTL)
#elif DRM_DEBUG_DEFAULT_ON == 2
#define DRM_DEBUGBITS_ON (DRM_UT_CORE | DRM_UT_DRIVER | DRM_UT_KMS | \
DRM_UT_PRIME| DRM_UT_ATOMIC | DRM_UT_FIOCTL | \
DRM_UT_PID | DRM_UT_IOCTL )
#else
#define DRM_DEBUGBITS_ON (0x0)
#endif
unsigned int drm_debug = DRM_DEBUGBITS_ON;
#else
unsigned int drm_debug = 0;
#endif
EXPORT_SYMBOL(drm_debug);
MODULE_AUTHOR("Gareth Hughes, Leif Delgass, José Fonseca, Jon Smirl");
MODULE_DESCRIPTION("DRM shared core routines");
MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug category.\n"
"\t\tBit 0 (0x01) will enable CORE messages (drm core code)\n"
"\t\tBit 1 (0x02) will enable DRIVER messages (drm controller code)\n"
"\t\tBit 2 (0x04) will enable KMS messages (modesetting code)\n"
"\t\tBit 3 (0x08) will enable PRIME messages (prime code)\n"
"\t\tBit 4 (0x10) will enable ATOMIC messages (atomic code)\n"
"\t\tBit 5 (0x20) will enable VBL messages (vblank code)\n"
"\t\tBit 7 (0x80) will enable LEASE messages (leasing code)\n"
"\t\tBit 8 (0x100) will enable DP messages (displayport code)");
module_param_named(debug, drm_debug, int, 0600);
static DEFINE_MUTEX(drm_minor_lock);
static struct idr drm_minors_idr;
static bool drm_core_init_complete = false;
#if 0
static struct dentry *drm_debugfs_root;
#endif
#if 0
DEFINE_STATIC_SRCU(drm_unplug_srcu);
#endif
static struct drm_minor **drm_minor_get_slot(struct drm_device *dev,
unsigned int type)
{
switch (type) {
case DRM_MINOR_PRIMARY:
return &dev->primary;
case DRM_MINOR_RENDER:
return &dev->render;
default:
BUG();
}
}
static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
{
struct drm_minor *minor;
unsigned long flags;
int r;
minor = kzalloc(sizeof(*minor), GFP_KERNEL);
if (!minor)
return -ENOMEM;
minor->type = type;
minor->dev = dev;
idr_preload(GFP_KERNEL);
spin_lock_irqsave(&drm_minor_lock, flags);
r = idr_alloc(&drm_minors_idr,
NULL,
64 * type,
64 * (type + 1),
GFP_NOWAIT);
spin_unlock_irqrestore(&drm_minor_lock, flags);
idr_preload_end();
if (r < 0)
goto err_free;
minor->index = r;
minor->kdev = drm_sysfs_minor_alloc(minor);
if (IS_ERR(minor->kdev)) {
r = PTR_ERR(minor->kdev);
goto err_index;
}
*drm_minor_get_slot(dev, type) = minor;
return 0;
err_index:
spin_lock_irqsave(&drm_minor_lock, flags);
idr_remove(&drm_minors_idr, minor->index);
spin_unlock_irqrestore(&drm_minor_lock, flags);
err_free:
kfree(minor);
return r;
}
static void drm_minor_free(struct drm_device *dev, unsigned int type)
{
struct drm_minor **slot, *minor;
unsigned long flags;
slot = drm_minor_get_slot(dev, type);
minor = *slot;
if (!minor)
return;
#if 0
put_device(minor->kdev);
#endif
spin_lock_irqsave(&drm_minor_lock, flags);
idr_remove(&drm_minors_idr, minor->index);
spin_unlock_irqrestore(&drm_minor_lock, flags);
kfree(minor);
*slot = NULL;
}
static int drm_minor_register(struct drm_device *dev, unsigned int type)
{
struct drm_minor *minor;
unsigned long flags;
int ret;
DRM_DEBUG("\n");
minor = *drm_minor_get_slot(dev, type);
if (!minor)
return 0;
#if 0
ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root);
if (ret) {
DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
goto err_debugfs;
}
ret = device_add(minor->kdev);
if (ret)
goto err_debugfs;
#endif
spin_lock_irqsave(&drm_minor_lock, flags);
idr_replace(&drm_minors_idr, minor, minor->index);
spin_unlock_irqrestore(&drm_minor_lock, flags);
DRM_DEBUG("new minor registered %d\n", minor->index);
return 0;
#if 0
err_debugfs:
drm_debugfs_cleanup(minor);
#endif
return ret;
}
static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
{
struct drm_minor *minor;
unsigned long flags;
minor = *drm_minor_get_slot(dev, type);
#if 0
if (!minor || !device_is_registered(minor->kdev))
#else
if (!minor)
#endif
return;
spin_lock_irqsave(&drm_minor_lock, flags);
idr_replace(&drm_minors_idr, NULL, minor->index);
spin_unlock_irqrestore(&drm_minor_lock, flags);
#if 0
device_del(minor->kdev);
#endif
dev_set_drvdata(minor->kdev, NULL);
drm_debugfs_cleanup(minor);
}
struct drm_minor *drm_minor_acquire(unsigned int minor_id)
{
struct drm_minor *minor;
unsigned long flags;
spin_lock_irqsave(&drm_minor_lock, flags);
minor = idr_find(&drm_minors_idr, minor_id);
if (minor)
drm_dev_get(minor->dev);
spin_unlock_irqrestore(&drm_minor_lock, flags);
if (!minor) {
return ERR_PTR(-ENODEV);
} else if (drm_dev_is_unplugged(minor->dev)) {
drm_dev_put(minor->dev);
return ERR_PTR(-ENODEV);
}
return minor;
}
void drm_minor_release(struct drm_minor *minor)
{
drm_dev_put(minor->dev);
}
#if 0
void drm_put_dev(struct drm_device *dev)
{
DRM_DEBUG("\n");
if (!dev) {
DRM_ERROR("cleanup called no dev\n");
return;
}
drm_dev_unregister(dev);
drm_dev_put(dev);
}
EXPORT_SYMBOL(drm_put_dev);
#endif
bool drm_dev_enter(struct drm_device *dev, int *idx)
{
#if 0
*idx = srcu_read_lock(&drm_unplug_srcu);
if (dev->unplugged) {
srcu_read_unlock(&drm_unplug_srcu, *idx);
return false;
}
#endif
return true;
}
EXPORT_SYMBOL(drm_dev_enter);
void drm_dev_exit(int idx)
{
#if 0
srcu_read_unlock(&drm_unplug_srcu, idx);
#endif
}
EXPORT_SYMBOL(drm_dev_exit);
void drm_dev_unplug(struct drm_device *dev)
{
STUB();
#if 0
dev->unplugged = true;
synchronize_srcu(&drm_unplug_srcu);
drm_dev_unregister(dev);
mutex_lock(&drm_global_mutex);
if (dev->open_count == 0)
drm_dev_put(dev);
mutex_unlock(&drm_global_mutex);
#endif
}
EXPORT_SYMBOL(drm_dev_unplug);
#if 0
static int drm_fs_cnt;
static struct vfsmount *drm_fs_mnt;
static const struct dentry_operations drm_fs_dops = {
.d_dname = simple_dname,
};
static const struct super_operations drm_fs_sops = {
.statfs = simple_statfs,
};
static struct dentry *drm_fs_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, void *data)
{
return mount_pseudo(fs_type,
"drm:",
&drm_fs_sops,
&drm_fs_dops,
0x010203ff);
}
static struct file_system_type drm_fs_type = {
.name = "drm",
.owner = THIS_MODULE,
.mount = drm_fs_mount,
.kill_sb = kill_anon_super,
};
static struct inode *drm_fs_inode_new(void)
{
struct inode *inode;
int r;
r = simple_pin_fs(&drm_fs_type, &drm_fs_mnt, &drm_fs_cnt);
if (r < 0) {
DRM_ERROR("Cannot mount pseudo fs: %d\n", r);
return ERR_PTR(r);
}
inode = alloc_anon_inode(drm_fs_mnt->mnt_sb);
if (IS_ERR(inode))
simple_release_fs(&drm_fs_mnt, &drm_fs_cnt);
return inode;
}
static void drm_fs_inode_free(struct inode *inode)
{
if (inode) {
iput(inode);
simple_release_fs(&drm_fs_mnt, &drm_fs_cnt);
}
}
#endif
int drm_dev_init(struct drm_device *dev,
struct drm_driver *driver,
struct device *parent)
{
int ret;
#ifdef __DragonFly__
struct drm_softc *softc = device_get_softc(parent->bsddev);
softc->drm_driver_data = dev;
#endif
if (!drm_core_init_complete) {
DRM_ERROR("DRM core is not initialized\n");
return -ENODEV;
}
kref_init(&dev->ref);
dev->dev = parent;
dev->driver = driver;
dev->driver_features = ~0u;
INIT_LIST_HEAD(&dev->filelist);
INIT_LIST_HEAD(&dev->filelist_internal);
INIT_LIST_HEAD(&dev->clientlist);
INIT_LIST_HEAD(&dev->ctxlist);
INIT_LIST_HEAD(&dev->vmalist);
INIT_LIST_HEAD(&dev->maplist);
INIT_LIST_HEAD(&dev->vblank_event_list);
lockinit(&dev->buf_lock, "drmdbl", 0, 0);
lockinit(&dev->event_lock, "drmev", 0, 0);
lockinit(&dev->struct_mutex, "drmslk", 0, LK_CANRECURSE);
lockinit(&dev->filelist_mutex, "drmflm", 0, LK_CANRECURSE);
lockinit(&dev->clientlist_mutex, "drmclm", 0, LK_CANRECURSE);
lockinit(&dev->ctxlist_mutex, "drmclm", 0, LK_CANRECURSE);
lockinit(&dev->master_mutex, "drmmm", 0, LK_CANRECURSE);
#ifndef __DragonFly__
dev->anon_inode = drm_fs_inode_new();
if (IS_ERR(dev->anon_inode)) {
ret = PTR_ERR(dev->anon_inode);
DRM_ERROR("Cannot allocate anonymous inode: %d\n", ret);
goto err_free;
}
#else
dev->anon_inode = NULL;
dev->pci_domain = pci_get_domain(dev->dev->bsddev);
dev->pci_bus = pci_get_bus(dev->dev->bsddev);
dev->pci_slot = pci_get_slot(dev->dev->bsddev);
dev->pci_func = pci_get_function(dev->dev->bsddev);
drm_sysctl_init(dev);
#endif
if (drm_core_check_feature(dev, DRIVER_RENDER)) {
ret = drm_minor_alloc(dev, DRM_MINOR_RENDER);
if (ret)
goto err_minors;
}
ret = drm_minor_alloc(dev, DRM_MINOR_PRIMARY);
if (ret)
goto err_minors;
ret = drm_ht_create(&dev->map_hash, 12);
if (ret)
goto err_minors;
drm_legacy_ctxbitmap_init(dev);
if (drm_core_check_feature(dev, DRIVER_GEM)) {
ret = drm_gem_init(dev);
if (ret) {
DRM_ERROR("Cannot initialize graphics execution manager (GEM)\n");
goto err_ctxbitmap;
}
}
#if 0
ret = drm_dev_set_unique(dev, parent ? dev_name(parent) : driver->name);
if (ret)
goto err_setunique;
#endif
return 0;
#if 0
err_setunique:
if (drm_core_check_feature(dev, DRIVER_GEM))
drm_gem_destroy(dev);
#endif
err_ctxbitmap:
drm_legacy_ctxbitmap_cleanup(dev);
drm_ht_remove(&dev->map_hash);
err_minors:
drm_minor_free(dev, DRM_MINOR_PRIMARY);
drm_minor_free(dev, DRM_MINOR_RENDER);
#ifndef __DragonFly__
drm_fs_inode_free(dev->anon_inode);
err_free:
#endif
mutex_destroy(&dev->master_mutex);
mutex_destroy(&dev->ctxlist_mutex);
mutex_destroy(&dev->clientlist_mutex);
mutex_destroy(&dev->filelist_mutex);
mutex_destroy(&dev->struct_mutex);
#ifdef __DragonFly__
drm_sysctl_cleanup(dev);
#endif
return ret;
}
EXPORT_SYMBOL(drm_dev_init);
void drm_dev_fini(struct drm_device *dev)
{
drm_vblank_cleanup(dev);
if (drm_core_check_feature(dev, DRIVER_GEM))
drm_gem_destroy(dev);
drm_legacy_ctxbitmap_cleanup(dev);
drm_ht_remove(&dev->map_hash);
#if 0
drm_fs_inode_free(dev->anon_inode);
#endif
drm_minor_free(dev, DRM_MINOR_PRIMARY);
drm_minor_free(dev, DRM_MINOR_RENDER);
#if 0
put_device(dev->dev);
#endif
mutex_destroy(&dev->master_mutex);
mutex_destroy(&dev->ctxlist_mutex);
mutex_destroy(&dev->clientlist_mutex);
mutex_destroy(&dev->filelist_mutex);
mutex_destroy(&dev->struct_mutex);
kfree(dev->unique);
}
EXPORT_SYMBOL(drm_dev_fini);
struct drm_device *drm_dev_alloc(struct drm_driver *driver,
struct device *parent)
{
struct drm_device *dev;
int ret;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return ERR_PTR(-ENOMEM);
ret = drm_dev_init(dev, driver, parent);
if (ret) {
kfree(dev);
return ERR_PTR(ret);
}
return dev;
}
EXPORT_SYMBOL(drm_dev_alloc);
static void drm_dev_release(struct kref *ref)
{
struct drm_device *dev = container_of(ref, struct drm_device, ref);
if (dev->driver->release) {
dev->driver->release(dev);
} else {
drm_dev_fini(dev);
kfree(dev);
}
}
void drm_dev_get(struct drm_device *dev)
{
if (dev)
kref_get(&dev->ref);
}
EXPORT_SYMBOL(drm_dev_get);
void drm_dev_put(struct drm_device *dev)
{
if (dev)
kref_put(&dev->ref, drm_dev_release);
}
EXPORT_SYMBOL(drm_dev_put);
void drm_dev_unref(struct drm_device *dev)
{
drm_dev_put(dev);
}
EXPORT_SYMBOL(drm_dev_unref);
static int create_compat_control_link(struct drm_device *dev)
{
struct drm_minor *minor;
char *name;
int ret;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return 0;
minor = *drm_minor_get_slot(dev, DRM_MINOR_PRIMARY);
if (!minor)
return 0;
name = kasprintf(GFP_KERNEL, "controlD%d", minor->index + 64);
if (!name)
return -ENOMEM;
#ifndef __DragonFly__
ret = sysfs_create_link(minor->kdev->kobj.parent,
&minor->kdev->kobj,
name);
#else
ret = 0;
#endif
kfree(name);
return ret;
}
static void remove_compat_control_link(struct drm_device *dev)
{
struct drm_minor *minor;
char *name;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return;
minor = *drm_minor_get_slot(dev, DRM_MINOR_PRIMARY);
if (!minor)
return;
name = kasprintf(GFP_KERNEL, "controlD%d", minor->index + 64);
if (!name)
return;
#ifndef __DragonFly__
sysfs_remove_link(minor->kdev->kobj.parent, name);
#endif
kfree(name);
}
int drm_dev_register(struct drm_device *dev, unsigned long flags)
{
struct drm_driver *driver = dev->driver;
int ret;
mutex_lock(&drm_global_mutex);
ret = drm_minor_register(dev, DRM_MINOR_RENDER);
if (ret)
goto err_minors;
ret = drm_minor_register(dev, DRM_MINOR_PRIMARY);
if (ret)
goto err_minors;
ret = create_compat_control_link(dev);
if (ret)
goto err_minors;
dev->registered = true;
if (dev->driver->load) {
ret = dev->driver->load(dev, flags);
if (ret)
goto err_minors;
}
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_register_all(dev);
ret = 0;
DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
driver->name, driver->major, driver->minor,
driver->patchlevel, driver->date,
dev->dev ? dev_name(dev->dev) : "virtual device",
dev->primary->index);
goto out_unlock;
err_minors:
remove_compat_control_link(dev);
drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
drm_minor_unregister(dev, DRM_MINOR_RENDER);
out_unlock:
mutex_unlock(&drm_global_mutex);
return ret;
}
EXPORT_SYMBOL(drm_dev_register);
void drm_dev_unregister(struct drm_device *dev)
{
struct drm_map_list *r_list, *list_temp;
if (drm_core_check_feature(dev, DRIVER_LEGACY))
drm_lastclose(dev);
dev->registered = false;
#if 0
drm_client_dev_unregister(dev);
#endif
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_unregister_all(dev);
if (dev->driver->unload)
dev->driver->unload(dev);
#if 0
if (dev->agp)
drm_pci_agp_destroy(dev);
#endif
list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
drm_legacy_rmmap(dev, r_list->map);
remove_compat_control_link(dev);
drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
drm_minor_unregister(dev, DRM_MINOR_RENDER);
}
EXPORT_SYMBOL(drm_dev_unregister);
#if 0
int drm_dev_set_unique(struct drm_device *dev, const char *name)
{
kfree(dev->unique);
dev->unique = kstrdup(name, GFP_KERNEL);
return dev->unique ? 0 : -ENOMEM;
}
EXPORT_SYMBOL(drm_dev_set_unique);
static int drm_stub_open(struct inode *inode, struct file *filp)
{
const struct file_operations *new_fops;
struct drm_minor *minor;
int err;
DRM_DEBUG("\n");
mutex_lock(&drm_global_mutex);
minor = drm_minor_acquire(iminor(inode));
if (IS_ERR(minor)) {
err = PTR_ERR(minor);
goto out_unlock;
}
new_fops = fops_get(minor->dev->driver->fops);
if (!new_fops) {
err = -ENODEV;
goto out_release;
}
replace_fops(filp, new_fops);
if (filp->f_op->open)
err = filp->f_op->open(inode, filp);
else
err = 0;
out_release:
drm_minor_release(minor);
out_unlock:
mutex_unlock(&drm_global_mutex);
return err;
}
static const struct file_operations drm_stub_fops = {
.owner = THIS_MODULE,
.open = drm_stub_open,
.llseek = noop_llseek,
};
#endif
static void drm_core_exit(void)
{
#if 0
unregister_chrdev(DRM_MAJOR, "drm");
debugfs_remove(drm_debugfs_root);
drm_sysfs_destroy();
#endif
idr_destroy(&drm_minors_idr);
drm_connector_ida_destroy();
drm_global_release();
}
static int __init drm_core_init(void)
{
#if 0
int ret;
#endif
drm_global_init();
drm_connector_ida_init();
idr_init(&drm_minors_idr);
#if 0
ret = drm_sysfs_init();
if (ret < 0) {
DRM_ERROR("Cannot create DRM class: %d\n", ret);
goto error;
}
drm_debugfs_root = debugfs_create_dir("dri", NULL);
if (!drm_debugfs_root) {
ret = -ENOMEM;
DRM_ERROR("Cannot create debugfs-root: %d\n", ret);
goto error;
}
ret = register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops);
if (ret < 0)
goto error;
#endif
drm_core_init_complete = true;
DRM_DEBUG("Initialized\n");
return 0;
#if 0
error:
drm_core_exit();
return ret;
#endif
}
module_init(drm_core_init);
module_exit(drm_core_exit);
#include <sys/devfs.h>
#include <linux/export.h>
#include <linux/dmi.h>
#include <drm/drmP.h>
static int
drm_modevent(module_t mod, int type, void *data)
{
switch (type) {
case MOD_LOAD:
TUNABLE_INT_FETCH("drm.debug", &drm_debug);
linux_task_drop_callback = linux_task_drop;
linux_proc_drop_callback = linux_proc_drop;
break;
case MOD_UNLOAD:
linux_task_drop_callback = NULL;
linux_proc_drop_callback = NULL;
break;
}
return (0);
}
static moduledata_t drm_mod = {
"drm",
drm_modevent,
0
};
DECLARE_MODULE(drm, drm_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
MODULE_VERSION(drm, 1);
MODULE_DEPEND(drm, agp, 1, 1, 1);
MODULE_DEPEND(drm, pci, 1, 1, 1);
MODULE_DEPEND(drm, iicbus, 1, 1, 1);
struct dev_ops drm_cdevsw = {
{ "drm", 0, D_TRACKCLOSE | D_MPSAFE },
.d_open = drm_open,
.d_close = drm_close,
.d_read = drm_read,
.d_ioctl = drm_ioctl,
.d_kqfilter = drm_kqfilter,
.d_mmap = drm_mmap,
.d_mmap_single = drm_mmap_single,
};
SYSCTL_NODE(_hw, OID_AUTO, drm, CTLFLAG_RW, NULL, "DRM device");
SYSCTL_INT(_hw_drm, OID_AUTO, debug, CTLFLAG_RW, &drm_debug, 0,
"DRM debugging");
int drm_vma_debug;
SYSCTL_INT(_hw_drm, OID_AUTO, vma_debug, CTLFLAG_RW, &drm_vma_debug, 0,
"DRM debugging");
#if 0
int
drm_create_cdevs(device_t kdev)
{
struct drm_device *dev;
int error, unit;
#ifdef __DragonFly__
struct drm_softc *softc = device_get_softc(kdev);
dev = softc->drm_driver_data;
#endif
unit = device_get_unit(kdev);
dev->devnode = make_dev(&drm_cdevsw, unit, DRM_DEV_UID, DRM_DEV_GID,
DRM_DEV_MODE, "dri/card%d", unit);
error = 0;
if (error == 0)
dev->devnode->si_drv1 = dev;
return (error);
}
#endif
#ifndef DRM_DEV_NAME
#define DRM_DEV_NAME "drm"
#endif
devclass_t drm_devclass;
void drm_cdevpriv_dtor(void *cd)
{
struct drm_file *file_priv = cd;
struct drm_device *dev = file_priv->dev;
DRM_DEBUG("open_count = %d\n", dev->open_count);
DRM_LOCK(dev);
if (dev->driver->preclose != NULL)
dev->driver->preclose(dev, file_priv);
DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
DRM_CURRENTPID, (long)dev->dev, dev->open_count);
if (dev->driver->driver_features & DRIVER_GEM)
drm_gem_release(dev, file_priv);
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
drm_legacy_reclaim_buffers(dev, file_priv);
funsetown(&dev->buf_sigio);
if (dev->driver->postclose != NULL)
dev->driver->postclose(dev, file_priv);
list_del(&file_priv->lhead);
device_unbusy(dev->dev->bsddev);
if (--dev->open_count == 0) {
drm_lastclose(dev);
}
DRM_UNLOCK(dev);
}
int
drm_add_busid_modesetting(struct drm_device *dev, struct sysctl_ctx_list *ctx,
struct sysctl_oid *top)
{
struct sysctl_oid *oid;
ksnprintf(dev->busid_str, sizeof(dev->busid_str),
"pci:%04x:%02x:%02x.%d", dev->pci_domain, dev->pci_bus,
dev->pci_slot, dev->pci_func);
oid = SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(top), OID_AUTO, "busid",
CTLFLAG_RD, dev->busid_str, 0, NULL);
if (oid == NULL)
return (ENOMEM);
return (0);
}
int
drm_mmap_single(struct dev_mmap_single_args *ap)
{
struct drm_device *dev;
struct cdev *kdev = ap->a_head.a_dev;
vm_ooffset_t *offset = ap->a_offset;
vm_size_t size = ap->a_size;
struct vm_object **obj_res = ap->a_object;
int nprot = ap->a_nprot;
dev = drm_get_device_from_kdev(kdev);
if (dev->drm_ttm_bdev != NULL) {
return (ttm_bo_mmap_single(ap->a_fp, dev,
offset, size, obj_res, nprot));
} else if ((dev->driver->driver_features & DRIVER_GEM) != 0) {
return (drm_gem_mmap_single(dev, offset, size, obj_res, nprot));
} else {
return (ENODEV);
}
}
#include <linux/dmi.h>
static bool
dmi_found(const struct dmi_system_id *dsi)
{
int i, slot;
bool found = false;
char *sys_vendor, *board_vendor, *product_name, *board_name;
sys_vendor = kgetenv("smbios.system.maker");
board_vendor = kgetenv("smbios.planar.maker");
product_name = kgetenv("smbios.system.product");
board_name = kgetenv("smbios.planar.product");
for (i = 0; i < NELEM(dsi->matches); i++) {
slot = dsi->matches[i].slot;
switch (slot) {
case DMI_NONE:
break;
case DMI_SYS_VENDOR:
if (sys_vendor != NULL &&
!strcmp(sys_vendor, dsi->matches[i].substr))
break;
else
goto done;
case DMI_BOARD_VENDOR:
if (board_vendor != NULL &&
!strcmp(board_vendor, dsi->matches[i].substr))
break;
else
goto done;
case DMI_PRODUCT_NAME:
if (product_name != NULL &&
!strcmp(product_name, dsi->matches[i].substr))
break;
else
goto done;
case DMI_BOARD_NAME:
if (board_name != NULL &&
!strcmp(board_name, dsi->matches[i].substr))
break;
else
goto done;
default:
goto done;
}
}
found = true;
done:
if (sys_vendor != NULL)
kfreeenv(sys_vendor);
if (board_vendor != NULL)
kfreeenv(board_vendor);
if (product_name != NULL)
kfreeenv(product_name);
if (board_name != NULL)
kfreeenv(board_name);
return found;
}
int dmi_check_system(const struct dmi_system_id *sysid)
{
const struct dmi_system_id *dsi;
int num = 0;
for (dsi = sysid; dsi->matches[0].slot != 0 ; dsi++) {
if (dmi_found(dsi)) {
num++;
if (dsi->callback && dsi->callback(dsi))
break;
}
}
return (num);
}