ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

RTCAN 驱动模块到RTDM 中

2022-02-22 17:01:57  阅读:177  来源: 互联网

标签:RTCAN dev drv ret 模块 device RTDM minor


1 .rtCAN 驱动模块到RTDM 中

int __init rtcan_init(void)
{
    int err = 0;

    if (!realtime_core_enabled())
	    return 0;

    printk("RT-Socket-CAN %d.%d.%d - %s\n",
	   RTCAN_MAJOR_VER, RTCAN_MINOR_VER, RTCAN_BUGFIX_VER,
	   rtcan_rtdm_provider_name);

    if ((err = rtcan_raw_proto_register()) != 0)
	goto out;

#ifdef CONFIG_PROC_FS
    if ((err = rtcan_proc_register()) != 0)
	goto out;
#endif

 out:
    return err;
}
module_init(rtcan_init);

rtcan_init()->rtcan_raw_proto_register()
其中 rtcan_raw_proto_register()

int __init rtcan_raw_proto_register(void)
{
    return rtdm_dev_register(&rtcan_device);
}

rtcan_init()->rtcan_raw_proto_register()->rtdm_dev_register(&rtcan_device)
rtdm_dev_register(&rtcan_device)
注册RTDM设备

/**
 * @brief Register a RTDM device
 *
 * Registers a device in the RTDM namespace.
 *
 * @param[in] dev Device descriptor.
 *
 * @return 0 is returned upon success. Otherwise:
 *
 * - -EINVAL is returned if the descriptor contains invalid
 * entries. RTDM_PROFILE_INFO() must appear in the list of
 * initializers for the driver properties.
 *
 * - -EEXIST is returned if the specified device name of protocol ID is
 * already in use.
 *
 * - -ENOMEM is returned if a memory allocation failed in the process
 * of registering the device.
 *
 * - -EAGAIN is returned if no registry slot is available (check/raise
 * CONFIG_XENO_OPT_REGISTRY_NRSLOTS).
 *
 * @coretags{secondary-only}
 */
int rtdm_dev_register(struct rtdm_device *dev)
{
	struct class *kdev_class = rtdm_class;
	struct device *kdev = NULL;
	struct rtdm_driver *drv;
	int ret, major, minor;
	xnkey_t id;
	dev_t rdev;

	secondary_mode_only();

	if (!realtime_core_enabled())
		return -ENOSYS;

	mutex_lock(&register_lock);

	dev->name = NULL;
	drv = dev->driver;
	ret = register_driver(drv);
	if (ret) {
		mutex_unlock(&register_lock);
		return ret;
	}

	dev->ops = drv->ops;
	if (drv->device_flags & RTDM_NAMED_DEVICE)
		dev->ops.socket = (typeof(dev->ops.socket))enosys;
	else
		dev->ops.open = (typeof(dev->ops.open))enosys;

	init_waitqueue_head(&dev->putwq);
	dev->ops.close = __rtdm_dev_close; /* Interpose on driver's handler. */
	atomic_set(&dev->refcount, 0);

	if (drv->profile_info.kdev_class)
		kdev_class = drv->profile_info.kdev_class;

	if (drv->device_flags & RTDM_NAMED_DEVICE) {
		if (drv->device_flags & RTDM_FIXED_MINOR) {
			minor = dev->minor;
			if (minor < 0 ||
			    minor >= drv->base_minor + drv->device_count) {
				ret = -ENXIO;
				goto fail;
			}
		} else {
			minor = find_first_zero_bit(drv->minor_map, RTDM_MAX_MINOR);
			if (minor >= RTDM_MAX_MINOR) {
				ret = -ENXIO;
				goto fail;
			}
			dev->minor = minor;
		}

		major = drv->named.major;
		dev->name = kasformat(dev->label, minor);
		if (dev->name == NULL) {
			ret = -ENOMEM;
			goto fail;
		}

		ret = xnregistry_enter(dev->name, dev,
				       &dev->named.handle, NULL);
		if (ret)
			goto fail;

		rdev = MKDEV(major, minor);
		kdev = device_create(kdev_class, NULL, rdev,
				     dev, kbasename(dev->label), minor);
		if (IS_ERR(kdev)) {
			xnregistry_remove(dev->named.handle);
			ret = PTR_ERR(kdev);
			goto fail;
		}
		__set_bit(minor, drv->minor_map);
	} else {
		minor = find_first_zero_bit(protocol_devices_minor_map,
					RTDM_MAX_MINOR);
		if (minor >= RTDM_MAX_MINOR) {
			ret = -ENXIO;
			goto fail;
		}
		dev->minor = minor;

		dev->name = kstrdup(dev->label, GFP_KERNEL);
		if (dev->name == NULL) {
			ret = -ENOMEM;
			goto fail;
		}

		rdev = MKDEV(0, minor);
		kdev = device_create(kdev_class, NULL, rdev,
				     dev, dev->name);
		if (IS_ERR(kdev)) {
			ret = PTR_ERR(kdev);
			goto fail;
		}

		id = get_proto_id(drv->protocol_family, drv->socket_type);
		ret = xnid_enter(&protocol_devices, &dev->proto.id, id);
		if (ret < 0)
			goto fail;
		__set_bit(minor, protocol_devices_minor_map);
	}

	dev->rdev = rdev;
	dev->kdev = kdev;
	dev->magic = RTDM_DEVICE_MAGIC;
	dev->kdev_class = kdev_class;

	mutex_unlock(&register_lock);

	trace_cobalt_device_register(dev);

	return 0;
fail:
	if (kdev)
		device_destroy(kdev_class, rdev);

	unregister_driver(drv);

	mutex_unlock(&register_lock);

	if (dev->name)
		kfree(dev->name);

	return ret;
}

rtcan_init()->rtcan_raw_proto_register()->rtdm_dev_register(&rtcan_device)-> register_driver()
注册驱动
register_driver()

static int register_driver(struct rtdm_driver *drv)
{
	dev_t rdev;
	int ret;

	if (drv->profile_info.magic == RTDM_CLASS_MAGIC) {
		atomic_inc(&drv->refcount);
		return 0;
	}

	if (drv->profile_info.magic != ~RTDM_CLASS_MAGIC) {
		XENO_WARN_ON_ONCE(COBALT, 1);
		return -EINVAL;
	}

	switch (drv->device_flags & RTDM_DEVICE_TYPE_MASK) {
	case RTDM_NAMED_DEVICE:
	case RTDM_PROTOCOL_DEVICE:
		break;
	default:
		printk(XENO_WARNING "%s has invalid device type (%#x)\n",
		       drv->profile_info.name,
		       drv->device_flags & RTDM_DEVICE_TYPE_MASK);
		return -EINVAL;
	}

	if (drv->device_count <= 0 ||
	    drv->device_count > RTDM_MAX_MINOR) {
		printk(XENO_WARNING "%s has invalid device count (%d)\n",
		       drv->profile_info.name, drv->device_count);
		return -EINVAL;
	}

	if ((drv->device_flags & RTDM_NAMED_DEVICE) == 0)
		goto done;

	if (drv->base_minor < 0 ||
	    drv->base_minor >= RTDM_MAX_MINOR) {
		printk(XENO_WARNING "%s has invalid base minor (%d)\n",
		       drv->profile_info.name, drv->base_minor);
		return -EINVAL;
	}

	ret = alloc_chrdev_region(&rdev, drv->base_minor, drv->device_count,
				  drv->profile_info.name);
		/*alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
			const char *name)
		让内核分配给我们一个尚未使用的主设备号,
		调用该函数后自动分配得到的设备号保存在dev中
		dev :alloc_chrdev_region函数向内核申请下来的设备号

		baseminor :次设备号的起始

		count: 申请次设备号的个数

		name :执行 cat /proc/devices显示的名称*/
	if (ret) {
		printk(XENO_WARNING "cannot allocate chrdev region %s[%d..%d]\n",
		       drv->profile_info.name, drv->base_minor,
		       drv->base_minor + drv->device_count - 1);
		return ret;
	}

	cdev_init(&drv->named.cdev, &rtdm_dumb_fops);
	ret = cdev_add(&drv->named.cdev, rdev, drv->device_count);
	/*1.执行cdev_init函数,将cdev和file_operations关联起来

	  2.使用cdev_add函数,将cdev和设备号关联起来
	*/
	if (ret) {
		printk(XENO_WARNING "cannot create cdev series for %s\n",
		       drv->profile_info.name);
		goto fail_cdev;
	}

	drv->named.major = MAJOR(rdev);
	bitmap_zero(drv->minor_map, RTDM_MAX_MINOR);

done:
	atomic_set(&drv->refcount, 1);
	drv->nb_statechange.notifier_call = state_change_notifier;
	drv->nb_statechange.priority = 0;
	cobalt_add_state_chain(&drv->nb_statechange);
	drv->profile_info.magic = RTDM_CLASS_MAGIC;

	return 0;

fail_cdev:
	unregister_chrdev_region(rdev, drv->device_count);

	return ret;
}

标签:RTCAN,dev,drv,ret,模块,device,RTDM,minor
来源: https://blog.csdn.net/robot1701/article/details/104537512

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有