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(®ister_lock);
dev->name = NULL;
drv = dev->driver;
ret = register_driver(drv);
if (ret) {
mutex_unlock(®ister_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(®ister_lock);
trace_cobalt_device_register(dev);
return 0;
fail:
if (kdev)
device_destroy(kdev_class, rdev);
unregister_driver(drv);
mutex_unlock(®ister_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