其他分享
首页 > 其他分享> > RTCAN 驱动模块到RTDM 中

RTCAN 驱动模块到RTDM 中

作者:互联网

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