Module: xenomai-forge
Branch: next
Commit: d817163953a063d5e7746f1273231d08629b1432
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=d817163953a063d5e7746f1273231d08629b1432

Author: Philippe Gerum <r...@xenomai.org>
Date:   Sun Sep 14 18:52:18 2014 +0200

cobalt/rtdm: split class / device

---

 include/cobalt/kernel/rtdm/analogy/context.h |    2 +-
 include/cobalt/kernel/rtdm/driver.h          |  192 ++++++++++------
 include/cobalt/kernel/rtdm/udd.h             |   11 +-
 kernel/cobalt/posix/io.c                     |   43 ----
 kernel/cobalt/posix/memory.c                 |   63 ++++--
 kernel/cobalt/rtdm/core.c                    |   43 ++--
 kernel/cobalt/rtdm/device.c                  |  312 +++++++++++++++++---------
 kernel/cobalt/rtdm/fd.c                      |   43 ++++
 kernel/cobalt/rtdm/internal.h                |    2 +-
 kernel/cobalt/rtdm/proc.c                    |   68 +++---
 kernel/cobalt/trace/cobalt-rtdm.h            |   24 +-
 kernel/drivers/analogy/rtdm_interface.c      |   76 ++++---
 kernel/drivers/autotune/autotune.c           |   17 +-
 kernel/drivers/can/rtcan_raw.c               |   21 +-
 kernel/drivers/ipc/rtipc.c                   |   28 ++-
 kernel/drivers/serial/16550A.c               |   40 ++--
 kernel/drivers/serial/mpc52xx_uart.c         |    1 -
 kernel/drivers/serial/rt_imx_uart.c          |    1 -
 kernel/drivers/testing/rtdmtest.c            |   63 +++---
 kernel/drivers/testing/switchtest.c          |   58 +++--
 kernel/drivers/testing/timerbench.c          |   60 ++---
 kernel/drivers/udd/udd.c                     |   86 +++----
 22 files changed, 732 insertions(+), 522 deletions(-)

diff --git a/include/cobalt/kernel/rtdm/analogy/context.h 
b/include/cobalt/kernel/rtdm/analogy/context.h
index 35d356d..71a292c 100644
--- a/include/cobalt/kernel/rtdm/analogy/context.h
+++ b/include/cobalt/kernel/rtdm/analogy/context.h
@@ -43,7 +43,7 @@ static inline int a4l_get_minor(struct a4l_device_context 
*cxt)
        /* Get a pointer on the container structure */
        struct rtdm_fd *fd = rtdm_private_to_fd(cxt);
        /* Get the minor index */
-       return rtdm_fd_device(fd)->device_id;
+       return rtdm_fd_minor(fd);
 }
 
 #endif /* !_COBALT_RTDM_ANALOGY_CONTEXT_H */
diff --git a/include/cobalt/kernel/rtdm/driver.h 
b/include/cobalt/kernel/rtdm/driver.h
index 29045cc..f6b3c92 100644
--- a/include/cobalt/kernel/rtdm/driver.h
+++ b/include/cobalt/kernel/rtdm/driver.h
@@ -27,7 +27,7 @@
 
 #include <asm/atomic.h>
 #include <linux/list.h>
-
+#include <linux/cdev.h>
 #include <xenomai/version.h>
 #include <cobalt/kernel/heap.h>
 #include <cobalt/kernel/sched.h>
@@ -51,7 +51,7 @@
 #endif /* CONFIG_PCI */
 #include <asm/xenomai/syscall.h>
 
-struct rtdm_dev_context;
+struct class;
 typedef struct xnselector rtdm_selector_t;
 enum rtdm_selecttype;
 
@@ -81,23 +81,17 @@ enum rtdm_selecttype;
 
 /** Mask selecting the device type. */
 #define RTDM_DEVICE_TYPE_MASK          0x00F0
+
+/** Flag indicating a secure variant of RTDM (not supported here) */
+#define RTDM_SECURE_DEVICE             0x80000000
 /** @} Device Flags */
 
 /*!
  * @anchor drv_versioning @name Driver Versioning
- * Current revisions of RTDM structures, encoding of driver versions. See
+ * Encoding of driver versions. See
  * @ref rtdm_api_versioning "API Versioning" for the interface revision.
  * @{
  */
-/** Version of struct rtdm_device */
-#define RTDM_DEVICE_STRUCT_VER         7
-
-/** Version of struct rtdm_dev_context */
-#define RTDM_CONTEXT_STRUCT_VER                4
-
-/** Flag indicating a secure variant of RTDM (not supported here) */
-#define RTDM_SECURE_DEVICE             0x80000000
-
 /** Version code constructor for driver revisions */
 #define RTDM_DRIVER_VER(major, minor, patch) \
        (((major & 0xFF) << 16) | ((minor & 0xFF) << 8) | (patch & 0xFF))
@@ -138,10 +132,6 @@ enum rtdm_selecttype {
 
 /** @} rtdm_sync */
 
-struct rtdm_devctx_reserved {
-       void (*close)(struct rtdm_fd *fd);
-};
-
 /**
  * @brief Device context
  *
@@ -149,9 +139,9 @@ struct rtdm_devctx_reserved {
  * RTDM takes care of its creation and destruction and passes it to the
  * operation handlers when being invoked.
  *
- * Drivers can attach arbitrary data immediately after the official structure.
- * The size of this data is provided via rtdm_device.context_size during
- * device registration.
+ * Drivers can attach arbitrary data immediately after the official
+ * structure.  The size of this data is provided via
+ * rtdm_device_class.context_size during device registration.
  */
 struct rtdm_dev_context {
        struct rtdm_fd fd;
@@ -160,9 +150,6 @@ struct rtdm_dev_context {
        /** Reference to owning device */
        struct rtdm_device *device;
 
-       /** Data stored by RTDM inside a device context (internal use only) */
-       struct rtdm_devctx_reserved reserved;
-
        /** Begin of driver defined context data structure */
        char dev_private[0];
 };
@@ -183,7 +170,7 @@ static inline struct rtdm_dev_context 
*rtdm_fd_to_context(struct rtdm_fd *fd)
  */
 static inline void *rtdm_fd_to_private(struct rtdm_fd *fd)
 {
-       return (void *)rtdm_fd_to_context(fd)->dev_private;
+       return &rtdm_fd_to_context(fd)->dev_private[0];
 }
 
 /**
@@ -227,79 +214,148 @@ static inline struct rtdm_device *rtdm_fd_device(struct 
rtdm_fd *fd)
        return rtdm_fd_to_context(fd)->device;
 }
 
-struct rtdm_dev_reserved {
-       unsigned magic;
-       union {
-               struct {
-                       struct list_head entry;
-                       xnhandle_t handle;
-               };
-               struct xnid id;
-       };
-       atomic_t refcount;
-       struct rtdm_dev_context *exclusive_context;
-       void (*close)(struct rtdm_fd *);
-};
+/**
+ * @brief RTDM profile information
+ *
+ * This descriptor details the profile information associated to a
+ * RTDM device class.
+ *
+ * @anchor rtdm_profile_info @name RTDM profile information descriptor
+ */
+struct rtdm_profile_info {
+       /** Device class name */
+       const char *name;
+       /** Device class ID, see @ref RTDM_CLASS_xxx */
+       int class_id;
+       /** Device sub-class, see RTDM_SUBCLASS_xxx definition in the
+        *  @ref rtdm_profiles "Device Profiles" */
+       int subclass_id;
+       /** Supported device profile version */
+       int version;
+       /** Reserved */
+       unsigned int magic;
+};     
 
 /**
- * @brief RTDM device
+ * @brief RTDM device class
  *
- * This structure specifies a RTDM device. As some fields, especially
- * the reserved area, will be modified by RTDM during runtime, the
- * structure must not reside in write-protected memory.
+ * This descriptor describes a RTDM device class. The structure holds
+ * runtime data, therefore it must reside in writable memory.
  */
-struct rtdm_device {
-       /** Data stored by RTDM inside a registered device (internal use only) 
*/
-       struct rtdm_dev_reserved reserved;
-       /** Revision number of this structure, see
-        *  @ref drv_versioning "Driver Versioning" defines */
-       int struct_version;
+struct rtdm_device_class {
+       /**
+        * Class profile information. The RTDM_PROFILE_INFO() macro @b
+        * must be used for filling up this field.
+        */
+       struct rtdm_profile_info profile_info;
        /** Device flags, see @ref dev_flags "Device Flags" for details */
        int device_flags;
        /** Size of driver defined appendix to struct rtdm_dev_context */
        size_t context_size;
-       /** Named device identification (orthogonal to Linux device name space) 
*/
-       char device_name[RTDM_MAX_DEVNAME_LEN + 1];
        /** Protocol device identification: protocol family (PF_xxx) */
        int protocol_family;
        /** Protocol device identification: socket type (SOCK_xxx) */
        int socket_type;
-       /** I/O operation handlers */
-       struct rtdm_fd_ops ops;
-       /** Device class ID, see @ref RTDM_CLASS_xxx */
-       int device_class;
-       /** Device sub-class, see RTDM_SUBCLASS_xxx definition in the
-        *  @ref rtdm_profiles "Device Profiles" */
-       int device_sub_class;
-       /** Supported device profile version */
-       int profile_version;
        /** Informational driver name (reported via /proc) */
        const char *driver_name;
-       /** Driver version, see @ref drv_versioning "Driver Versioning" defines 
*/
+       /** Driver version, see @ref drv_versioning "Driver Versioning" macros 
*/
        int driver_version;
        /** Informational peripheral name the device is attached to
         *  (reported via /proc) */
        const char *peripheral_name;
        /** Informational driver provider name (reported via /proc) */
        const char *provider_name;
-       /** Name of /proc entry for the device, must not be NULL */
-       const char *proc_name;
-#ifdef CONFIG_XENO_OPT_VFILE
-       /** Set to device's vfile data after registration, do not modify */
-       struct xnvfile_directory vfroot;
-       struct xnvfile_regular info_vfile;
-#endif
-       /** Driver definable device ID */
-       int device_id;
+       /** I/O operation handlers */
+       struct rtdm_fd_ops ops;
+       /** Count of devices which belong to this class. */
+       int device_count;
+       /** Reserved area */
+       struct {
+               union {
+                       struct {
+                               struct cdev cdev;
+                               struct class *kclass;
+                               int major;
+                       } named;
+               };
+               atomic_t refcount;
+       };
+};
+
+#define RTDM_CLASS_MAGIC       0x8284636c
+
+/**
+ * @brief Initializer for class profile information.
+ *
+ * This macro must be used to fill in the @ref rtdm_profile_info
+ * "class profile information" field from a RTDM device class.
+ *
+ * @param __name Class name (unquoted).
+ *
+ * @param __id Class major identification number
+ * (profile_version.class_id).
+ *
+ * @param __subid Class minor identification number
+ * (profile_version.subclass_id).
+ *
+ * @param __version Profile version number.
+ *
+ * @note See @ref rtdm_profiles "Device Profiles".
+ */
+#define RTDM_PROFILE_INFO(__name, __id, __subid, __version)    \
+{                                                              \
+       .name = ( # __name ),                                   \
+       .class_id = (__id),                                     \
+       .subclass_id = (__subid),                               \
+       .version = (__version),                                 \
+       .magic = ~RTDM_CLASS_MAGIC,                             \
+}
+
+/**
+ * @brief RTDM device
+ *
+ * This descriptor describes a RTDM device instance. The structure
+ * holds runtime data, therefore it must reside in writable memory.
+ */
+struct rtdm_device {
+       /** Device class. */
+       struct rtdm_device_class *class;
        /** Driver definable device data */
        void *device_data;
+       /** Device label template */
+       const char *label;
+       /** Reserved area. */
+       struct {
+               unsigned int magic;
+               char *name;
+               union {
+                       struct {
+                               struct list_head entry;
+                               xnhandle_t handle;
+                               int minor;
+                       } named;
+                       struct {
+                               struct xnid id;
+                       } proto;
+               };
+               atomic_t refcount;
+               struct rtdm_dev_context *exclusive_context;
+               struct rtdm_fd_ops ops;
+#ifdef CONFIG_XENO_OPT_VFILE
+               struct xnvfile_directory vfroot;
+               struct xnvfile_regular info_vfile;
+#endif
+       };
 };
+
 /** @} devregister */
 
 /* --- device registration --- */
 
 int rtdm_dev_register(struct rtdm_device *device);
-int rtdm_dev_unregister(struct rtdm_device *device, unsigned int poll_delay);
+
+int rtdm_dev_unregister(struct rtdm_device *device,
+                       unsigned int poll_delay);
 
 /* --- inter-driver API --- */
 
diff --git a/include/cobalt/kernel/rtdm/udd.h b/include/cobalt/kernel/rtdm/udd.h
index d21efc2..8fae461 100644
--- a/include/cobalt/kernel/rtdm/udd.h
+++ b/include/cobalt/kernel/rtdm/udd.h
@@ -129,10 +129,10 @@
  * the memory region array as follows:
  *
  * @code
+ * static struct udd_device udd;
+ *
  * static int foocard_pci_probe(struct pci_dev *dev, const struct 
pci_device_id *id)
  * {
- *      struct udd_device udd;
- *
  *      udd.device_name = "foocard";
  *      ...
  *      udd.mem_regions[2].name = "ADC";
@@ -189,7 +189,10 @@ struct udd_memregion {
  * mini-driver when registering via a call to udd_register_device().
  */
 struct udd_device {
-       /** Name of the device managed by the mini-driver. */
+       /**
+        * Name of the device managed by the mini-driver, appears
+        * automatically in the /dev namespace upon creation.
+        */
        const char *device_name;
        /**
         * Additional device flags (e.g. RTDM_EXCLUSIVE,
@@ -289,7 +292,9 @@ struct udd_device {
                atomic_t event;
                struct udd_signotify signfy;
                struct rtdm_event pulse;
+               struct rtdm_device_class class;
                struct rtdm_device device;
+               struct rtdm_device_class mapper_class;
                struct rtdm_device mapper;
                char *mapper_name;
                int nr_maps;
diff --git a/kernel/cobalt/posix/io.c b/kernel/cobalt/posix/io.c
index 4d549bb..9810c32 100644
--- a/kernel/cobalt/posix/io.c
+++ b/kernel/cobalt/posix/io.c
@@ -20,7 +20,6 @@
 #include <linux/err.h>
 #include <linux/file.h>
 #include <linux/fs.h>
-#include <linux/poll.h>
 #include <linux/fdtable.h>
 #include <linux/anon_inodes.h>
 #include <cobalt/kernel/ppd.h>
@@ -30,48 +29,6 @@
 #include "clock.h"
 #include "io.h"
 
-static inline void warn_user(const char *name)
-{
-#ifdef CONFIG_XENO_OPT_DEBUG_USER
-       printk(XENO_WARN "%s[%d] called regular %s() with RTDM file/socket\n",
-              current->comm, current->pid, name + 5);
-#endif
-}
-
-static ssize_t dumb_read(struct file *file, char  __user *buf,
-                        size_t count, loff_t __user *ppos)
-{
-       warn_user(__func__);
-       return -EINVAL;
-}
-
-static ssize_t dumb_write(struct file *file,  const char __user *buf,
-                         size_t count, loff_t __user *ppos)
-{
-       warn_user(__func__);
-       return -EINVAL;
-}
-
-static unsigned int dumb_poll(struct file *file, poll_table *pt)
-{
-       warn_user(__func__);
-       return -EINVAL;
-}
-
-static long dumb_ioctl(struct file *file, unsigned int cmd,
-                      unsigned long arg)
-{
-       warn_user(__func__);
-       return -EINVAL;
-}
-
-const struct file_operations rtdm_dumb_fops = {
-       .read           = dumb_read,
-       .write          = dumb_write,
-       .poll           = dumb_poll,
-       .unlocked_ioctl = dumb_ioctl,
-};
-
 COBALT_SYSCALL(open, lostage,
               int, (const char __user *u_path, int oflag))
 {
diff --git a/kernel/cobalt/posix/memory.c b/kernel/cobalt/posix/memory.c
index 78cae01..92ba6fd 100644
--- a/kernel/cobalt/posix/memory.c
+++ b/kernel/cobalt/posix/memory.c
@@ -209,65 +209,80 @@ static int sysmem_ioctl_nrt(struct rtdm_fd *fd,
        return do_sysmem_ioctls(fd, request, arg);
 }
 
-static struct rtdm_device private_umm_device = {
-       .struct_version                 =       RTDM_DEVICE_STRUCT_VER,
-       .device_flags                   =       RTDM_NAMED_DEVICE,
-       .context_size                   =       0,
+static struct rtdm_device_class private_umm = {
+       .profile_info   =       RTDM_PROFILE_INFO(private_umm,
+                                                 RTDM_CLASS_MEMORY,
+                                                 UMM_PRIVATE,
+                                                 0),
+       .device_flags   =       RTDM_NAMED_DEVICE,
+       .device_count   =       1,
+       .context_size   =       0,
        .ops = {
                .ioctl_rt               =       umm_ioctl_rt,
                .ioctl_nrt              =       umm_ioctl_nrt,
                .mmap                   =       umm_mmap,
                .get_unmapped_area      =       umm_get_unmapped_area,
        },
-       .device_class           =       RTDM_CLASS_MEMORY,
-       .device_sub_class       =       UMM_PRIVATE,
-       .device_name            =       COBALT_MEMDEV_PRIVATE,
        .driver_name            =       "memdev",
        .driver_version         =       RTDM_DRIVER_VER(1, 0, 0),
        .peripheral_name        =       "Private user-mapped heap",
-       .proc_name              =       private_umm_device.device_name,
        .provider_name          =       "Philippe Gerum <r...@xenomai.org>",
 };
 
-static struct rtdm_device shared_umm_device = {
-       .struct_version                 =       RTDM_DEVICE_STRUCT_VER,
-       .device_flags                   =       RTDM_NAMED_DEVICE,
-       .context_size                   =       0,
+static struct rtdm_device private_umm_device = {
+       .class = &private_umm,
+       .label = COBALT_MEMDEV_PRIVATE,
+};
+
+static struct rtdm_device_class shared_umm = {
+       .profile_info   =       RTDM_PROFILE_INFO(shared_umm,
+                                                 RTDM_CLASS_MEMORY,
+                                                 UMM_SHARED,
+                                                 0),
+       .device_flags   =       RTDM_NAMED_DEVICE,
+       .device_count   =       1,
+       .context_size   =       0,
        .ops = {
                .ioctl_rt               =       umm_ioctl_rt,
                .ioctl_nrt              =       umm_ioctl_nrt,
                .mmap                   =       umm_mmap,
                .get_unmapped_area      =       umm_get_unmapped_area,
        },
-       .device_class           =       RTDM_CLASS_MEMORY,
-       .device_sub_class       =       UMM_SHARED,
-       .device_name            =       COBALT_MEMDEV_SHARED,
        .driver_name            =       "memdev",
        .driver_version         =       RTDM_DRIVER_VER(1, 0, 0),
        .peripheral_name        =       "Shared user-mapped heap",
-       .proc_name              =       shared_umm_device.device_name,
        .provider_name          =       "Philippe Gerum <r...@xenomai.org>",
 };
 
-static struct rtdm_device sysmem_device = {
-       .struct_version         =       RTDM_DEVICE_STRUCT_VER,
-       .device_flags           =       RTDM_NAMED_DEVICE,
-       .context_size           =       0,
+static struct rtdm_device shared_umm_device = {
+       .class = &shared_umm,
+       .label = COBALT_MEMDEV_SHARED,
+};
+
+static struct rtdm_device_class sysmem = {
+       .profile_info   =       RTDM_PROFILE_INFO(sysmem,
+                                                 RTDM_CLASS_MEMORY,
+                                                 SYS_GLOBAL,
+                                                 0),
+       .device_flags   =       RTDM_NAMED_DEVICE,
+       .device_count   =       1,
+       .context_size   =       0,
        .ops = {
                .open           =       sysmem_open,
                .ioctl_rt       =       sysmem_ioctl_rt,
                .ioctl_nrt      =       sysmem_ioctl_nrt,
        },
-       .device_class           =       RTDM_CLASS_MEMORY,
-       .device_sub_class       =       SYS_GLOBAL,
-       .device_name            =       COBALT_MEMDEV_SYS,
        .driver_name            =       "memdev",
        .driver_version         =       RTDM_DRIVER_VER(1, 0, 0),
        .peripheral_name        =       "System memory heap",
-       .proc_name              =       sysmem_device.device_name,
        .provider_name          =       "Philippe Gerum <r...@xenomai.org>",
 };
 
+static struct rtdm_device sysmem_device = {
+       .class = &sysmem,
+       .label = COBALT_MEMDEV_SYS,
+};
+
 static inline void init_vdso(void)
 {
        nkvdso->features = XNVDSO_FEATURES;
diff --git a/kernel/cobalt/rtdm/core.c b/kernel/cobalt/rtdm/core.c
index f84d8b0..56ecbaa 100644
--- a/kernel/cobalt/rtdm/core.c
+++ b/kernel/cobalt/rtdm/core.c
@@ -44,7 +44,7 @@ static void cleanup_instance(struct rtdm_device *device,
                             struct rtdm_dev_context *context)
 {
        if (context) {
-               if (device->reserved.exclusive_context)
+               if (device->exclusive_context)
                        context->device = NULL;
                else
                        kfree(context);
@@ -56,9 +56,13 @@ static void cleanup_instance(struct rtdm_device *device,
 void __rt_dev_close(struct rtdm_fd *fd)
 {
        struct rtdm_dev_context *context = rtdm_fd_to_context(fd);
-       if (context->reserved.close)
-               context->reserved.close(fd);
-       cleanup_instance(context->device, context);
+       struct rtdm_device *device = context->device;
+       struct rtdm_device_class *class = device->class;
+
+       if (class->ops.close)
+               class->ops.close(fd);
+
+       cleanup_instance(device, context);
 }
 
 void __rt_dev_unref(struct rtdm_fd *fd, unsigned int idx)
@@ -75,8 +79,8 @@ void __rt_dev_unref(struct rtdm_fd *fd, unsigned int idx)
 }
 
 static int create_instance(struct xnsys_ppd *p, int fd,
-                       struct rtdm_device *device,
-                       struct rtdm_dev_context **context_ptr)
+                          struct rtdm_device *device,
+                          struct rtdm_dev_context **context_ptr)
 {
        struct rtdm_dev_context *context;
        spl_t s;
@@ -103,7 +107,7 @@ static int create_instance(struct xnsys_ppd *p, int fd,
                xnlock_put_irqrestore(&rt_fildes_lock, s);
        }
 
-       context = device->reserved.exclusive_context;
+       context = device->exclusive_context;
        if (context) {
                xnlock_get_irqsave(&rt_dev_lock, s);
 
@@ -118,7 +122,7 @@ static int create_instance(struct xnsys_ppd *p, int fd,
                xnlock_put_irqrestore(&rt_dev_lock, s);
        } else {
                context = kmalloc(sizeof(struct rtdm_dev_context) +
-                               device->context_size, GFP_KERNEL);
+                               device->class->context_size, GFP_KERNEL);
                if (unlikely(context == NULL)) {
                        err = -ENOMEM;
                        goto fail;
@@ -127,7 +131,6 @@ static int create_instance(struct xnsys_ppd *p, int fd,
                context->device = device;
        }
 
-       context->reserved.close = device->reserved.close;
        *context_ptr = context;
 
        err = rtdm_fd_enter(p, &context->fd, fd, RTDM_FD_MAGIC, &device->ops);
@@ -165,7 +168,10 @@ int __rt_dev_open(struct xnsys_ppd *p, int ufd, const char 
*path, int oflag)
                goto cleanup_out;
 
        ufd = ret;
-       context->fd.minor = minor;
+       if (device->class->device_flags & RTDM_NAMED_DEVICE)
+               context->fd.minor = device->named.minor;
+       else
+               context->fd.minor = minor;
 
        trace_cobalt_fd_open(current, &context->fd, ufd, oflag);
 
@@ -191,8 +197,8 @@ EXPORT_SYMBOL_GPL(__rt_dev_open);
 int __rt_dev_socket(struct xnsys_ppd *p, int ufd, int protocol_family,
                    int socket_type, int protocol)
 {
-       struct rtdm_device *device;
        struct rtdm_dev_context *context;
+       struct rtdm_device *device;
        int ret;
 
        device = __rtdm_get_protocol_device(protocol_family, socket_type);
@@ -225,19 +231,20 @@ cleanup_out:
 }
 EXPORT_SYMBOL_GPL(__rt_dev_socket);
 
-int
-__rt_dev_ioctl_fallback(struct rtdm_fd *fd, unsigned int request, void __user 
*arg)
+int __rt_dev_ioctl_fallback(struct rtdm_fd *fd, unsigned int request,
+                           void __user *arg)
 {
-       struct rtdm_device *dev = rtdm_fd_device(fd);
+       struct rtdm_device *device = rtdm_fd_device(fd);
+       struct rtdm_device_class *class = device->class;
        struct rtdm_device_info dev_info;
 
        if (fd->magic != RTDM_FD_MAGIC || request != RTIOC_DEVICE_INFO)
                return -ENOSYS;
 
-       dev_info.device_flags = dev->device_flags;
-       dev_info.device_class = dev->device_class;
-       dev_info.device_sub_class = dev->device_sub_class;
-       dev_info.profile_version = dev->profile_version;
+       dev_info.device_flags = class->device_flags;
+       dev_info.device_class = class->profile_info.class_id;
+       dev_info.device_sub_class = class->profile_info.subclass_id;
+       dev_info.profile_version = class->profile_info.version;
 
        return rtdm_safe_copy_to_user(fd, arg, &dev_info,  sizeof(dev_info));
 }
diff --git a/kernel/cobalt/rtdm/device.c b/kernel/cobalt/rtdm/device.c
index d513685..39d42b0 100644
--- a/kernel/cobalt/rtdm/device.c
+++ b/kernel/cobalt/rtdm/device.c
@@ -23,7 +23,7 @@
 #include <linux/semaphore.h>
 #include <linux/slab.h>
 #include <linux/ctype.h>
-#include <cobalt/kernel/apc.h>
+#include <linux/device.h>
 #include "rtdm/internal.h"
 #include <trace/events/cobalt-rtdm.h>
 
@@ -45,15 +45,15 @@ static int enosys(void)
        return -ENOSYS;
 }
 
-static inline unsigned long long get_proto_id(int pf, int type)
+static inline xnkey_t get_proto_id(int pf, int type)
 {
-       unsigned long long llpf = (unsigned)pf;
-       return (llpf << 32) | (unsigned)type;
+       xnkey_t llpf = (unsigned int)pf;
+       return (llpf << 32) | (unsigned int)type;
 }
 
 static inline void rtdm_reference_device(struct rtdm_device *device)
 {
-       atomic_inc(&device->reserved.refcount);
+       atomic_inc(&device->refcount);
 }
 
 struct rtdm_device *__rtdm_get_named_device(const char *name, int *minor_r)
@@ -105,8 +105,8 @@ struct rtdm_device *__rtdm_get_named_device(const char 
*name, int *minor_r)
 
        device = xnregistry_lookup(handle, NULL);
        if (device) {
-               if (device->reserved.magic == RTDM_DEVICE_MAGIC &&
-                   ((device->device_flags & RTDM_MINOR) != 0 ||
+               if (device->magic == RTDM_DEVICE_MAGIC &&
+                   ((device->class->device_flags & RTDM_MINOR) != 0 ||
                     minor < 0)) {
                        rtdm_reference_device(device);
                        *minor_r = minor;
@@ -122,9 +122,9 @@ struct rtdm_device *__rtdm_get_named_device(const char 
*name, int *minor_r)
 struct rtdm_device *
 __rtdm_get_protocol_device(int protocol_family, int socket_type)
 {
-       struct rtdm_device *device;
-       unsigned long long id;
+       struct rtdm_device *device = NULL;
        struct xnid *xnid;
+       xnkey_t id;
        spl_t s;
 
        id = get_proto_id(protocol_family, socket_type);
@@ -133,11 +133,9 @@ __rtdm_get_protocol_device(int protocol_family, int 
socket_type)
 
        xnid = xnid_fetch(&rtdm_protocol_devices, id);
        if (xnid) {
-               device = container_of(xnid, struct rtdm_device, reserved.id);
-
+               device = container_of(xnid, struct rtdm_device, proto.id);
                rtdm_reference_device(device);
-       } else
-               device = NULL;
+       }
 
        xnlock_put_irqrestore(&rt_dev_lock, s);
 
@@ -150,143 +148,248 @@ __rtdm_get_protocol_device(int protocol_family, int 
socket_type)
  * @{
  */
 
+static char *rtdm_devnode(struct device *dev, umode_t *mode)
+{
+       return kasprintf(GFP_KERNEL, "rtdm/%s", dev_name(dev));
+}
+
+static int register_device_class(struct rtdm_device_class *class)
+{
+       struct class *kclass;
+       dev_t rdev;
+       int ret;
+
+       if (class->profile_info.magic == RTDM_CLASS_MAGIC) {
+               atomic_inc(&class->refcount);
+               return 0;
+       }
+
+       if (class->profile_info.magic != ~RTDM_CLASS_MAGIC)
+               return -EINVAL;
+
+       switch (class->device_flags & RTDM_DEVICE_TYPE_MASK) {
+       case RTDM_NAMED_DEVICE:
+       case RTDM_PROTOCOL_DEVICE:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (class->device_count <= 0)
+               return -EINVAL;
+
+       if ((class->device_flags & RTDM_NAMED_DEVICE) == 0)
+               goto done;
+
+       ret = alloc_chrdev_region(&rdev, 0, class->device_count,
+                                 class->profile_info.name);
+       if (ret) {
+               printk(XENO_WARN "cannot allocate chrdev region %s[0..%d]\n",
+                      class->profile_info.name, class->device_count - 1);
+               return ret;
+       }
+
+       cdev_init(&class->named.cdev, &rtdm_dumb_fops);
+       ret = cdev_add(&class->named.cdev, rdev, class->device_count);
+       if (ret)
+               goto fail_cdev;
+
+       kclass = class_create(THIS_MODULE, class->profile_info.name);
+       if (IS_ERR(kclass)) {
+               printk(XENO_WARN "cannot create device class %s\n",
+                      class->profile_info.name);
+               ret = PTR_ERR(kclass);
+               goto fail_class;
+       }
+       kclass->devnode = rtdm_devnode;
+
+       class->named.kclass = kclass;
+       class->named.major = MAJOR(rdev);
+       atomic_set(&class->refcount, 1);
+done:
+       class->profile_info.magic = RTDM_CLASS_MAGIC;
+
+       return 0;
+
+fail_class:
+       cdev_del(&class->named.cdev);
+fail_cdev:
+       unregister_chrdev_region(rdev, class->device_count);
+
+       return ret;
+}
+
+static void unregister_device_class(struct rtdm_device_class *class)
+{
+       XENO_BUGON(COBALT, class->profile_info.magic != RTDM_CLASS_MAGIC);
+
+       if (!atomic_dec_and_test(&class->refcount))
+               return;
+
+       if (class->device_flags & RTDM_NAMED_DEVICE) {
+               class_destroy(class->named.kclass);
+               cdev_del(&class->named.cdev);
+               unregister_chrdev_region(MKDEV(class->named.major, 0),
+                                        class->device_count);
+       }
+}
+
 /**
  * @brief Register a RTDM device
  *
- * @param[in] device Pointer to structure describing the new device.
+ * The device descriptor is initialized and registered in the RTDM
+ * namespace.
  *
- * @return 0 is returned upon success. Otherwise:
+ * @param[in] device Pointer to the device descriptor register.
+ * @param[in] class RTDM class the new device belongs to.
  *
- * - -EINVAL is returned if the device structure contains invalid entries.
- * Check kernel log in this case.
+ * @return 0 is returned upon success. Otherwise:
  *
- * - -ENOMEM is returned if a memory allocation failed in the process
- * of registering the device.
+ * - -EINVAL is returned if the descriptor contains invalid
+ * entries. RTDM_PROFILE_INFO() must appear in the list of
+ * initializers setting up the class properties.
  *
  * - -EEXIST is returned if the specified device name of protocol ID is
  * already in use.
  *
  * - -EAGAIN is returned if some /proc entry cannot be created.
  *
+ * - -ENOMEM is returned if a memory allocation failed in the process
+ * of registering the device.
+ *
+ * - -EAGAIN is returned if some /proc entry cannot be created.
+ *
  * @coretags{secondary-only}
  */
 int rtdm_dev_register(struct rtdm_device *device)
 {
-       unsigned long long id;
+       struct rtdm_device_class *class;
+       int ret, pos, major, minor;
+       struct device *kdev;
+       xnkey_t id;
        spl_t s;
-       int ret;
 
        if (!realtime_core_enabled())
                return -ENOSYS;
 
-       /* Sanity check: structure version */
-       if (!XENO_ASSERT(COBALT, device->struct_version == 
RTDM_DEVICE_STRUCT_VER)) {
-               printk(XENO_ERR "invalid rtdm_device version (%d, "
-                      "required %d)\n", device->struct_version,
-                      RTDM_DEVICE_STRUCT_VER);
-               return -EINVAL;
-       }
+       down(&nrt_dev_lock);
 
-       /* Sanity check: proc_name specified? */
-       if (!XENO_ASSERT(COBALT, device->proc_name)) {
-               printk(XENO_ERR "no vfile (/proc) name specified for RTDM 
device\n");
-               return -EINVAL;
+       device->name = NULL;
+       device->exclusive_context = NULL;
+       class = device->class;
+       pos = atomic_read(&class->refcount);
+       ret = register_device_class(class);
+       if (ret) {
+               up(&nrt_dev_lock);
+               return ret;
        }
 
-       switch (device->device_flags & RTDM_DEVICE_TYPE_MASK) {
-       case RTDM_NAMED_DEVICE:
+       device->ops = class->ops;
+       if (class->device_flags & RTDM_NAMED_DEVICE)
                device->ops.socket = (typeof(device->ops.socket))enosys;
-               break;
-
-       case RTDM_PROTOCOL_DEVICE:
+       else
                device->ops.open = (typeof(device->ops.open))enosys;
-               break;
 
-       default:
-               return -EINVAL;
-       }
+       device->ops.close = __rt_dev_close; /* Interpose on driver's handler. */
+       atomic_set(&device->refcount, 0);
 
-       device->reserved.close = device->ops.close;
-       device->ops.close = __rt_dev_close;
-       atomic_set(&device->reserved.refcount, 0);
-       device->reserved.exclusive_context = NULL;
-
-       if (device->device_flags & RTDM_EXCLUSIVE) {
-               device->reserved.exclusive_context =
-                   kmalloc(sizeof(struct rtdm_dev_context) +
-                           device->context_size, GFP_KERNEL);
-               if (!device->reserved.exclusive_context) {
-                       printk(XENO_ERR "no memory for exclusive context of 
RTDM device "
-                              "(context size: %ld)\n",
-                                (long)device->context_size);
-                       return -ENOMEM;
+       if (class->device_flags & RTDM_EXCLUSIVE) {
+               device->exclusive_context =
+                       kmalloc(sizeof(struct rtdm_dev_context) +
+                               class->context_size, GFP_KERNEL);
+               if (device->exclusive_context == NULL) {
+                       ret = -ENOMEM;
+                       goto fail;
                }
                /* mark exclusive context as unused */
-               device->reserved.exclusive_context->device = NULL;
+               device->exclusive_context->device = NULL;
        }
 
-       down(&nrt_dev_lock);
+       device->magic = RTDM_DEVICE_MAGIC;
 
-       trace_cobalt_device_register(device);
+       if (class->device_flags & RTDM_NAMED_DEVICE) {
+               major = class->named.major;
+               minor = pos;
+               device->named.minor = minor;
+               device->name = kasformat(device->label, minor);
+               if (device->name == NULL) {
+                       ret = -ENOMEM;
+                       goto fail;
+               }
 
-       device->reserved.magic = RTDM_DEVICE_MAGIC;
+               kdev = device_create(class->named.kclass, NULL,
+                                    MKDEV(major, minor),
+                                    device, device->label, minor);
+               if (IS_ERR(kdev)) {
+                       ret = PTR_ERR(kdev);
+                       goto fail;
+               }
 
-       if ((device->device_flags & RTDM_DEVICE_TYPE_MASK) ==
-               RTDM_NAMED_DEVICE) {
-               ret = rtdm_proc_register_device(device);
+               ret = xnregistry_enter(device->name, device,
+                                      &device->named.handle, NULL);
                if (ret)
-                       goto err;
-
-               ret = xnregistry_enter(device->device_name, device,
-                               &device->reserved.handle, NULL);
-               if (ret) {
-                       rtdm_proc_unregister_device(device);
-                       goto err;
-               }
+                       goto fail_register;
 
                xnlock_get_irqsave(&rt_dev_lock, s);
-               list_add_tail(&device->reserved.entry, &rtdm_named_devices);
+               list_add_tail(&device->named.entry, &rtdm_named_devices);
                xnlock_put_irqrestore(&rt_dev_lock, s);
 
-               up(&nrt_dev_lock);
-       } else {
-               id = get_proto_id(device->protocol_family,
-                               device->socket_type);
+               ret = rtdm_proc_register_device(device);
+               if (ret)
+                       goto fail_proc;
 
+       } else {
+               device->name = kstrdup(device->label, GFP_KERNEL);
+               if (device->name == NULL) {
+                       ret = -ENOMEM;
+                       goto fail;
+               }
+               id = get_proto_id(class->protocol_family, class->socket_type);
                xnlock_get_irqsave(&rt_dev_lock, s);
-               ret = xnid_enter(&rtdm_protocol_devices,
-                               &device->reserved.id, id);
+               ret = xnid_enter(&rtdm_protocol_devices, &device->proto.id, id);
                xnlock_put_irqrestore(&rt_dev_lock, s);
                if (ret < 0)
-                       goto err;
+                       goto fail;
 
                ret = rtdm_proc_register_device(device);
                if (ret) {
                        xnlock_get_irqsave(&rt_dev_lock, s);
-                       xnid_remove(&rtdm_protocol_devices,
-                               &device->reserved.id);
+                       xnid_remove(&rtdm_protocol_devices, &device->proto.id);
                        xnlock_put_irqrestore(&rt_dev_lock, s);
-                       goto err;
+                       goto fail;
                }
-
-               up(&nrt_dev_lock);
        }
+
+       up(&nrt_dev_lock);
+
+       trace_cobalt_device_register(device);
+
        return 0;
+fail_proc:
+       xnregistry_remove(device->named.handle);
+fail_register:
+       device_destroy(class->named.kclass, MKDEV(major, minor));
+fail:
+       unregister_device_class(class);
 
-err:
        up(&nrt_dev_lock);
-       if (device->reserved.exclusive_context)
-               kfree(device->reserved.exclusive_context);
+
+       if (device->name)
+               kfree(device->name);
+
+       if (device->exclusive_context)
+               kfree(device->exclusive_context);
+
        return ret;
 }
-
 EXPORT_SYMBOL_GPL(rtdm_dev_register);
 
 /**
- * @brief Unregisters a RTDM device
+ * @brief Unregister a RTDM device
+ *
+ * The device descriptor removed from the RTDM namespace.
  *
- * @param[in] device Pointer to structure describing the device to be
- * unregistered.
+ * @param[in] device Pointer to the device descriptor.
  * @param[in] poll_delay Polling delay in milliseconds to check repeatedly for
  * open instances of @a device, or 0 for non-blocking mode.
  *
@@ -299,13 +402,11 @@ EXPORT_SYMBOL_GPL(rtdm_dev_register);
  */
 int rtdm_dev_unregister(struct rtdm_device *device, unsigned int poll_delay)
 {
+       struct rtdm_device_class *class = device->class;
+       xnhandle_t handle = XN_NO_HANDLE;
        unsigned long warned = 0;
-       xnhandle_t handle = 0;
        spl_t s;
 
-       if (!realtime_core_enabled())
-               return -ENOSYS;
-
        rtdm_reference_device(device);
 
        trace_cobalt_device_unregister(device, poll_delay);
@@ -313,7 +414,7 @@ int rtdm_dev_unregister(struct rtdm_device *device, 
unsigned int poll_delay)
        down(&nrt_dev_lock);
        xnlock_get_irqsave(&rt_dev_lock, s);
 
-       while (atomic_read(&device->reserved.refcount) > 1) {
+       while (atomic_read(&device->refcount) > 1) {
                xnlock_put_irqrestore(&rt_dev_lock, s);
                up(&nrt_dev_lock);
 
@@ -324,18 +425,17 @@ int rtdm_dev_unregister(struct rtdm_device *device, 
unsigned int poll_delay)
 
                if (!__test_and_set_bit(0, &warned))
                        printk(XENO_WARN "RTDM device %s still in use - waiting 
for"
-                              " release...\n", device->device_name);
+                              " release...\n", device->name);
                msleep(poll_delay);
                down(&nrt_dev_lock);
                xnlock_get_irqsave(&rt_dev_lock, s);
        }
 
-       if ((device->device_flags & RTDM_DEVICE_TYPE_MASK) ==
-               RTDM_NAMED_DEVICE) {
-               handle = device->reserved.handle;
-               list_del(&device->reserved.entry);
+       if (class->device_flags & RTDM_NAMED_DEVICE) {
+               handle = device->named.handle;
+               list_del(&device->named.entry);
        } else
-               xnid_remove(&rtdm_protocol_devices, &device->reserved.id);
+               xnid_remove(&rtdm_protocol_devices, &device->proto.id);
 
        xnlock_put_irqrestore(&rt_dev_lock, s);
 
@@ -344,15 +444,19 @@ int rtdm_dev_unregister(struct rtdm_device *device, 
unsigned int poll_delay)
        if (handle)
                xnregistry_remove(handle);
 
+       unregister_device_class(class);
+
        up(&nrt_dev_lock);
 
-       if (device->reserved.exclusive_context)
-               kfree(device->reserved.exclusive_context);
+       if (device->exclusive_context)
+               kfree(device->exclusive_context);
+
+       kfree(device->name);
 
        return 0;
 }
-
 EXPORT_SYMBOL_GPL(rtdm_dev_unregister);
+
 /** @} */
 
 int __init rtdm_dev_init(void)
diff --git a/kernel/cobalt/rtdm/fd.c b/kernel/cobalt/rtdm/fd.c
index 9a7bb8c..8617e83 100644
--- a/kernel/cobalt/rtdm/fd.c
+++ b/kernel/cobalt/rtdm/fd.c
@@ -21,6 +21,7 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
+#include <linux/poll.h>
 #include <linux/kthread.h>
 #include <linux/semaphore.h>
 #include <cobalt/kernel/registry.h>
@@ -638,3 +639,45 @@ void rtdm_fd_init(void)
        sema_init(&rtdm_fd_cleanup_sem, 0);
        kthread_run(fd_cleanup_thread, NULL, "rtdm_fd");
 }
+
+static inline void warn_user(const char *name)
+{
+#ifdef CONFIG_XENO_OPT_DEBUG_USER
+       printk(XENO_WARN "%s[%d] called regular %s() with RTDM file/socket\n",
+              current->comm, current->pid, name + 5);
+#endif
+}
+
+static ssize_t dumb_read(struct file *file, char  __user *buf,
+                        size_t count, loff_t __user *ppos)
+{
+       warn_user(__func__);
+       return -EINVAL;
+}
+
+static ssize_t dumb_write(struct file *file,  const char __user *buf,
+                         size_t count, loff_t __user *ppos)
+{
+       warn_user(__func__);
+       return -EINVAL;
+}
+
+static unsigned int dumb_poll(struct file *file, poll_table *pt)
+{
+       warn_user(__func__);
+       return -EINVAL;
+}
+
+static long dumb_ioctl(struct file *file, unsigned int cmd,
+                      unsigned long arg)
+{
+       warn_user(__func__);
+       return -EINVAL;
+}
+
+const struct file_operations rtdm_dumb_fops = {
+       .read           = dumb_read,
+       .write          = dumb_write,
+       .poll           = dumb_poll,
+       .unlocked_ioctl = dumb_ioctl,
+};
diff --git a/kernel/cobalt/rtdm/internal.h b/kernel/cobalt/rtdm/internal.h
index 8012e22..985e01f 100644
--- a/kernel/cobalt/rtdm/internal.h
+++ b/kernel/cobalt/rtdm/internal.h
@@ -47,7 +47,7 @@ struct rtdm_device *__rtdm_get_protocol_device(int 
protocol_family, int socket_t
 
 static inline void rtdm_dereference_device(struct rtdm_device *device)
 {
-       atomic_dec(&device->reserved.refcount);
+       atomic_dec(&device->refcount);
 }
 
 int __init rtdm_dev_init(void);
diff --git a/kernel/cobalt/rtdm/proc.c b/kernel/cobalt/rtdm/proc.c
index 10f6cb2..52f6d8d 100644
--- a/kernel/cobalt/rtdm/proc.c
+++ b/kernel/cobalt/rtdm/proc.c
@@ -46,15 +46,14 @@ static void *named_next(struct xnvfile_regular_iterator *it)
        struct rtdm_device *device = priv->curr;
        struct list_head *next;
 
-       next = device->reserved.entry.next;
+       next = device->named.entry.next;
        if (next == &rtdm_named_devices) {
                priv->curr = NULL; /* all done. */
                goto out;
        }
 
-       priv->curr = list_entry(next, struct rtdm_device, reserved.entry);
-
-  out:
+       priv->curr = list_entry(next, struct rtdm_device, named.entry);
+out:
        return priv->curr;
 }
 
@@ -64,18 +63,18 @@ static void *named_begin(struct xnvfile_regular_iterator 
*it)
        struct rtdm_device *device;
        loff_t pos = 0;
 
-       list_for_each_entry(device, &rtdm_named_devices, reserved.entry)
+       list_for_each_entry(device, &rtdm_named_devices, named.entry)
                if (pos++ >= it->pos)
                        break;
 
-       if (&device->reserved.entry == &rtdm_named_devices)
+       if (&device->named.entry == &rtdm_named_devices)
                return NULL;    /* End of list. */
 
        priv->curr = device;    /* Skip head. */
 
        if (pos == 1)
                /* Output the header once, only if some device follows. */
-               xnvfile_puts(it, "Name\t\t\t\tDriver\t\t/proc\n");
+               xnvfile_puts(it, "Name\t\t\t\tDriver\n");
 
        return priv->curr;
 }
@@ -84,8 +83,8 @@ static int named_show(struct xnvfile_regular_iterator *it, 
void *data)
 {
        struct rtdm_device *device = data;
 
-       xnvfile_printf(it, "%-31s\t%-15s\t%s\n", device->device_name,
-               device->driver_name, device->proc_name);
+       xnvfile_printf(it, "%-31s\t%-15s\n", device->name,
+               device->class->driver_name);
 
        return 0;
 }
@@ -110,7 +109,7 @@ static void *proto_next(struct xnvfile_regular_iterator *it)
 {
        struct vfile_proto_data *priv = xnvfile_iterator_priv(it);
 
-       return priv->curr = xnid_next_entry(priv->curr, reserved.id);
+       return priv->curr = xnid_next_entry(priv->curr, proto.id);
 }
 
 static void *proto_begin(struct xnvfile_regular_iterator *it)
@@ -120,7 +119,7 @@ static void *proto_begin(struct xnvfile_regular_iterator 
*it)
        struct rtdm_device *dev = NULL;
        loff_t pos = 0;
 
-       xntree_for_each_entry(dev, &rtdm_protocol_devices, reserved.id)
+       xntree_for_each_entry(dev, &rtdm_protocol_devices, proto.id)
                if (pos++ >= it->pos)
                        break;
 
@@ -131,7 +130,7 @@ static void *proto_begin(struct xnvfile_regular_iterator 
*it)
 
        if (pos == 1)
                /* Output the header once, only if some device follows. */
-               xnvfile_puts(it, "Name\t\t\t\tDriver\t\t/proc\n");
+               xnvfile_puts(it, "Name\t\t\t\tDriver\n");
 
        return priv->curr;
 }
@@ -139,14 +138,15 @@ static void *proto_begin(struct xnvfile_regular_iterator 
*it)
 static int proto_show(struct xnvfile_regular_iterator *it, void *data)
 {
        struct rtdm_device *device = data;
+       struct rtdm_device_class *class = device->class;
        char pnum[32];
 
        ksformat(pnum, sizeof(pnum), "%u:%u",
-                device->protocol_family, device->socket_type);
+                class->protocol_family, class->socket_type);
 
        xnvfile_printf(it, "%-31s\t%-15s\t%s\n",
-                      pnum, device->driver_name,
-                      device->proc_name);
+                      pnum, class->driver_name,
+                      device->name);
        return 0;
 }
 
@@ -181,7 +181,6 @@ static void *openfd_next(struct xnvfile_regular_iterator 
*it)
 static int openfd_show(struct xnvfile_regular_iterator *it, void *data)
 {
        struct rtdm_dev_context *context;
-       struct rtdm_device *device;
        int close_lock_count, i;
        struct rtdm_fd *fd;
 
@@ -198,13 +197,10 @@ static int openfd_show(struct xnvfile_regular_iterator 
*it, void *data)
 
        context = rtdm_fd_to_context(fd);
        close_lock_count = fd->refs;
-       device = context->device;
 
        xnvfile_printf(it, "%d\t%d\t%d\t%s\n", i,
-                      close_lock_count,
-                      rtdm_fd_minor(fd),
-                      (device->device_flags & RTDM_NAMED_DEVICE) ?
-                      device->device_name : device->proc_name);
+                      close_lock_count, rtdm_fd_minor(fd),
+                      context->device->name);
 
        rtdm_fd_put(fd);
 
@@ -256,6 +252,7 @@ static struct xnvfile_regular allfd_vfile = {
 
 static int devinfo_vfile_show(struct xnvfile_regular_iterator *it, void *data)
 {
+       struct rtdm_device_class *class;
        struct rtdm_device *device;
 
        if (down_interruptible(&nrt_dev_lock))
@@ -265,11 +262,11 @@ static int devinfo_vfile_show(struct 
xnvfile_regular_iterator *it, void *data)
         * As the device may have disappeared while the handler was called,
         * first match the pointer against registered devices.
         */
-       list_for_each_entry(device, &rtdm_named_devices, reserved.entry)
+       list_for_each_entry(device, &rtdm_named_devices, named.entry)
                if (device == xnvfile_priv(it->vfile))
                        goto found;
 
-       xntree_for_each_entry(device, &rtdm_protocol_devices, reserved.id)
+       xntree_for_each_entry(device, &rtdm_protocol_devices, proto.id)
                if (device == xnvfile_priv(it->vfile))
                        goto found;
 
@@ -277,28 +274,31 @@ static int devinfo_vfile_show(struct 
xnvfile_regular_iterator *it, void *data)
        return -ENODEV;
 
 found:
+       class = device->class;
+
        xnvfile_printf(it, "driver:\t\t%s\nversion:\t%d.%d.%d\n",
-                      device->driver_name,
-                      RTDM_DRIVER_MAJOR_VER(device->driver_version),
-                      RTDM_DRIVER_MINOR_VER(device->driver_version),
-                      RTDM_DRIVER_PATCH_VER(device->driver_version));
+                      class->driver_name,
+                      RTDM_DRIVER_MAJOR_VER(class->driver_version),
+                      RTDM_DRIVER_MINOR_VER(class->driver_version),
+                      RTDM_DRIVER_PATCH_VER(class->driver_version));
 
        xnvfile_printf(it, "peripheral:\t%s\nprovider:\t%s\n",
-                      device->peripheral_name, device->provider_name);
+                      class->peripheral_name, class->provider_name);
 
        xnvfile_printf(it, "class:\t\t%d\nsub-class:\t%d\n",
-                      device->device_class, device->device_sub_class);
+                      class->profile_info.class_id,
+                      class->profile_info.subclass_id);
 
        xnvfile_printf(it, "flags:\t\t%s%s%s\n",
-                      (device->device_flags & RTDM_EXCLUSIVE) ?
+                      (class->device_flags & RTDM_EXCLUSIVE) ?
                       "EXCLUSIVE  " : "",
-                      (device->device_flags & RTDM_NAMED_DEVICE) ?
+                      (class->device_flags & RTDM_NAMED_DEVICE) ?
                       "NAMED_DEVICE  " : "",
-                      (device->device_flags & RTDM_PROTOCOL_DEVICE) ?
+                      (class->device_flags & RTDM_PROTOCOL_DEVICE) ?
                       "PROTOCOL_DEVICE  " : "");
 
        xnvfile_printf(it, "lock count:\t%d\n",
-                      atomic_read(&device->reserved.refcount));
+                      atomic_read(&device->refcount));
 
        up(&nrt_dev_lock);
        return 0;
@@ -312,7 +312,7 @@ int rtdm_proc_register_device(struct rtdm_device *device)
 {
        int ret;
 
-       ret = xnvfile_init_dir(device->proc_name,
+       ret = xnvfile_init_dir(device->name,
                               &device->vfroot, &rtdm_vfroot);
        if (ret)
                goto err_out;
diff --git a/kernel/cobalt/trace/cobalt-rtdm.h 
b/kernel/cobalt/trace/cobalt-rtdm.h
index 2754a67..4ca71ef 100644
--- a/kernel/cobalt/trace/cobalt-rtdm.h
+++ b/kernel/cobalt/trace/cobalt-rtdm.h
@@ -151,29 +151,29 @@ TRACE_EVENT(cobalt_device_register,
 
        TP_STRUCT__entry(
                __field(struct rtdm_device *, device)
-               __string(device_name, device->device_name)
+               __string(device_name, device->name)
                __field(int, flags)
-               __field(int, device_class)
-               __field(int, device_subclass)
+               __field(int, class_id)
+               __field(int, subclass_id)
                __field(int, profile_version)
                __field(int, driver_version)
        ),
 
        TP_fast_assign(
                __entry->device = device;
-               __assign_str(device_name, device->device_name);
-               __entry->flags = device->device_flags;
-               __entry->device_class = device->device_class;
-               __entry->device_subclass = device->device_sub_class;
-               __entry->profile_version = device->profile_version;
-               __entry->driver_version = device->driver_version;
+               __assign_str(device_name, device->class->device_name);
+               __entry->flags = device->class->device_flags;
+               __entry->class_id = device->class->device_class;
+               __entry->subclass_id = device->class->device_sub_class;
+               __entry->profile_version = device->class->profile_version;
+               __entry->driver_version = device->class->driver_version;
        ),
 
        TP_printk("%s device %s=%p version=%d flags=0x%x, class=%d.%d 
profile=%d",
                  (__entry->flags & RTDM_DEVICE_TYPE_MASK)
                  == RTDM_NAMED_DEVICE ? "named" : "protocol",
                  __get_str(device_name), __entry->device, 
__entry->driver_version,
-                 __entry->flags, __entry->device_class, 
__entry->device_subclass,
+                 __entry->flags, __entry->class_id, __entry->subclass_id,
                  __entry->profile_version)
 );
 
@@ -183,13 +183,13 @@ TRACE_EVENT(cobalt_device_unregister,
 
        TP_STRUCT__entry(
                __field(struct rtdm_device *, device)
-               __string(device_name, device->device_name)
+               __string(device_name, device->class->device_name)
                __field(unsigned int, poll_delay)
        ),
 
        TP_fast_assign(
                __entry->device = device;
-               __assign_str(device_name, device->device_name);
+               __assign_str(device_name, device->class->device_name);
                __entry->poll_delay = poll_delay;
        ),
 
diff --git a/kernel/drivers/analogy/rtdm_interface.c 
b/kernel/drivers/analogy/rtdm_interface.c
index aae78ff..926ee52 100644
--- a/kernel/drivers/analogy/rtdm_interface.c
+++ b/kernel/drivers/analogy/rtdm_interface.c
@@ -213,51 +213,53 @@ int a4l_rt_select(struct rtdm_fd *fd,
        return a4l_select(cxt, selector, type, fd_index);
 }
 
-static struct rtdm_device rtdm_devs[A4L_NB_DEVICES] =
-{[0 ... A4L_NB_DEVICES - 1] = {
-               .struct_version =       RTDM_DEVICE_STRUCT_VER,
-               .device_flags =         RTDM_NAMED_DEVICE,
-               .context_size =         sizeof(struct a4l_device_context),
-               .device_name =          "",
-               .ops = {
-                       .open =         a4l_open,
-                       .close =        a4l_close,
-                       .ioctl_rt =     a4l_ioctl,
-                       .read_rt =      a4l_read,
-                       .write_rt =     a4l_write,
-                       .ioctl_nrt =    a4l_ioctl,
-                       .read_nrt =     a4l_read,
-                       .write_nrt =    a4l_write,
-                       .select =       a4l_rt_select,
-               },
-               .device_class =         RTDM_CLASS_EXPERIMENTAL,
-               .device_sub_class =     RTDM_SUBCLASS_ANALOGY,
-               .driver_name =          "rtdm_analogy",
-               .driver_version =       RTDM_DRIVER_VER(1, 0, 0),
-               .peripheral_name =      "Analogy",
-               .provider_name =        "Alexis Berlemont",
+static struct rtdm_device_class analogy = {
+       .profile_info =         RTDM_PROFILE_INFO(analogy,
+                                                 RTDM_CLASS_EXPERIMENTAL,
+                                                 RTDM_SUBCLASS_ANALOGY,
+                                                 0),
+       .device_flags =         RTDM_NAMED_DEVICE,
+       .device_count =         A4L_NB_DEVICES,
+       .context_size =         sizeof(struct a4l_device_context),
+       .ops = {
+               .open =         a4l_open,
+               .close =        a4l_close,
+               .ioctl_rt =     a4l_ioctl,
+               .read_rt =      a4l_read,
+               .write_rt =     a4l_write,
+               .ioctl_nrt =    a4l_ioctl,
+               .read_nrt =     a4l_read,
+               .write_nrt =    a4l_write,
+               .select =       a4l_rt_select,
+       },
+       .driver_name =          "analogy",
+       .driver_version =       RTDM_DRIVER_VER(1, 0, 0),
+       .peripheral_name =      "Analogy",
+       .provider_name =        "Alexis Berlemont",
+};
+
+static struct rtdm_device rtdm_devs[A4L_NB_DEVICES] = {
+       [0 ... A4L_NB_DEVICES - 1] = {
+               .class = &analogy,
+               .label = "analogy%d",
        }
 };
 
 int a4l_register(void)
 {
-       int i, ret = 0;
-
-       for (i = 0; i < A4L_NB_DEVICES && ret == 0; i++) {
-
-               /* Sets the device name through which
-                  user process can access the Analogy layer */
-               ksformat(rtdm_devs[i].device_name,
-                        RTDM_MAX_DEVNAME_LEN, "analogy%d", i);
-               rtdm_devs[i].proc_name = rtdm_devs[i].device_name;
+       int i, ret;
 
-               /* To keep things simple, the RTDM device ID
-                  is the Analogy device index */
-               rtdm_devs[i].device_id = i;
-
-               ret = rtdm_dev_register(&(rtdm_devs[i]));
+       for (i = 0; i < A4L_NB_DEVICES; i++) {
+               ret = rtdm_dev_register(rtdm_devs + i);
+               if (ret)
+                       goto fail;
        }
 
+       return 0;
+fail:
+       while (i-- > 0)
+               rtdm_dev_unregister(rtdm_devs + i, 0);
+
        return ret;
 }
 
diff --git a/kernel/drivers/autotune/autotune.c 
b/kernel/drivers/autotune/autotune.c
index 8e9b040..c407038 100644
--- a/kernel/drivers/autotune/autotune.c
+++ b/kernel/drivers/autotune/autotune.c
@@ -628,9 +628,13 @@ static void autotune_close(struct rtdm_fd *fd)
                tuner->destroy_tuner(tuner);
 }
 
-static struct rtdm_device device = {
-       .struct_version         =       RTDM_DEVICE_STRUCT_VER,
+static struct rtdm_device_class autotune = {
+       .profile_info           =       RTDM_PROFILE_INFO(autotune,
+                                                         RTDM_CLASS_AUTOTUNE,
+                                                         
RTDM_SUBCLASS_AUTOTUNE,
+                                                         0),
        .device_flags           =       RTDM_NAMED_DEVICE|RTDM_EXCLUSIVE,
+       .device_count           =       1,
        .context_size           =       sizeof(struct autotune_context),
        .ops = {
                .open           =       autotune_open,
@@ -638,16 +642,17 @@ static struct rtdm_device device = {
                .ioctl_nrt      =       autotune_ioctl_nrt,
                .close          =       autotune_close,
        },
-       .device_class           =       RTDM_CLASS_AUTOTUNE,
-       .device_sub_class       =       RTDM_SUBCLASS_AUTOTUNE,
-       .device_name            =       "autotune",
        .driver_name            =       "autotune",
        .driver_version         =       RTDM_DRIVER_VER(1, 0, 0),
        .peripheral_name        =       "Auto-tuning services",
-       .proc_name              =       device.device_name,
        .provider_name          =       "Philippe Gerum <r...@xenomai.org>",
 };
 
+static struct rtdm_device device = {
+       .class = &autotune,
+       .label = "autotune",
+};
+
 static int __init autotune_init(void)
 {
        int ret;
diff --git a/kernel/drivers/can/rtcan_raw.c b/kernel/drivers/can/rtcan_raw.c
index e658ea3..17e19f1 100644
--- a/kernel/drivers/can/rtcan_raw.c
+++ b/kernel/drivers/can/rtcan_raw.c
@@ -62,7 +62,7 @@ MODULE_LICENSE("GPL");
 void rtcan_tx_push(struct rtcan_device *dev, struct rtcan_socket *sock,
                   can_frame_t *frame);
 
-static struct rtdm_device rtcan_proto_raw_dev;
+static struct rtdm_device_class rtcan_proto_raw;
 
 
 static inline int rtcan_accept_msg(uint32_t can_id, can_filter_t *filter)
@@ -128,7 +128,7 @@ static void rtcan_rcv_deliver(struct rtcan_recv 
*recv_listener,
        /* Overflow of socket's ring buffer! */
        sock->rx_buf_full++;
        RTCAN_RTDM_DBG("%s: socket buffer overflow, message discarded\n",
-                      rtcan_proto_raw_dev.driver_name);
+                      rtcan_proto_raw.driver_name);
     }
 
     rtdm_fd_unlock(fd);
@@ -976,9 +976,13 @@ ssize_t rtcan_raw_sendmsg(struct rtdm_fd *fd,
 }
 
 
-static struct rtdm_device rtcan_proto_raw_dev = {
-       .struct_version         = RTDM_DEVICE_STRUCT_VER,
+static struct rtdm_device_class rtcan_proto_raw = {
+       .profile_info           = RTDM_PROFILE_INFO(rtcan_proto_raw,
+                                                   RTDM_CLASS_CAN,
+                                                   RTDM_SUBCLASS_GENERIC,
+                                                   RTCAN_PROFILE_VER),
        .device_flags           = RTDM_PROTOCOL_DEVICE,
+       .device_count           = 1,
        .context_size           = sizeof(struct rtcan_socket),
        .protocol_family        = PF_CAN,
        .socket_type            = SOCK_RAW,
@@ -990,25 +994,24 @@ static struct rtdm_device rtcan_proto_raw_dev = {
                .recvmsg_rt     = rtcan_raw_recvmsg,
                .sendmsg_rt     = rtcan_raw_sendmsg,
        },
-       .device_class           = RTDM_CLASS_CAN,
-       .device_sub_class       = RTDM_SUBCLASS_GENERIC,
-       .profile_version        = RTCAN_PROFILE_VER,
        .driver_name            = "rtcan",
        .driver_version         = RTDM_DRIVER_VER(RTCAN_MAJOR_VER,
                                                  RTCAN_MINOR_VER,
                                                  RTCAN_BUGFIX_VER),
        .peripheral_name        = "Real-Time CAN Raw Socket Interface",
        .provider_name          = "RT-Socket-CAN development team",
-       .proc_name              = "rtcan"
 };
 
+static struct rtdm_device rtcan_proto_raw_dev = {
+       .class = &rtcan_proto_raw,
+       .label = "rtcan",
+};
 
 int __init rtcan_raw_proto_register(void)
 {
     return rtdm_dev_register(&rtcan_proto_raw_dev);
 }
 
-
 void __exit rtcan_raw_proto_unregister(void)
 {
     rtdm_dev_unregister(&rtcan_proto_raw_dev, 1000);
diff --git a/kernel/drivers/ipc/rtipc.c b/kernel/drivers/ipc/rtipc.c
index 802b7f4..e64c22f 100644
--- a/kernel/drivers/ipc/rtipc.c
+++ b/kernel/drivers/ipc/rtipc.c
@@ -252,13 +252,16 @@ static int rtipc_select(struct rtdm_fd *fd, struct 
xnselector *selector,
        return ret;
 }
 
-static struct rtdm_device device = {
-       .struct_version =       RTDM_DEVICE_STRUCT_VER,
-       .device_flags   =       RTDM_PROTOCOL_DEVICE,
-       .context_size   =       sizeof(struct rtipc_private),
-       .device_name    =       "rtipc",
-       .protocol_family=       PF_RTIPC,
-       .socket_type    =       SOCK_DGRAM,
+static struct rtdm_device_class rtipc = {
+       .profile_info           =       RTDM_PROFILE_INFO(rtipc,
+                                                         RTDM_CLASS_RTIPC,
+                                                         RTDM_SUBCLASS_GENERIC,
+                                                         1),
+       .device_flags           =       RTDM_PROTOCOL_DEVICE,
+       .device_count           =       1,
+       .context_size           =       sizeof(struct rtipc_private),
+       .protocol_family        =       PF_RTIPC,
+       .socket_type            =       SOCK_DGRAM,
        .ops = {
                .socket         =       rtipc_socket,
                .close          =       rtipc_close,
@@ -274,14 +277,15 @@ static struct rtdm_device device = {
                .write_nrt      =       NULL,
                .select         =       rtipc_select,
        },
-       .device_class           =       RTDM_CLASS_RTIPC,
-       .device_sub_class       =       RTDM_SUBCLASS_GENERIC,
-       .profile_version        =       1,
        .driver_name            =       "rtipc",
        .driver_version         =       RTDM_DRIVER_VER(1, 0, 0),
        .peripheral_name        =       "Real-time IPC interface",
-       .proc_name              =       device.device_name,
-       .provider_name          =       "Philippe Gerum (xenomai.org)",
+       .provider_name          =       "Philippe Gerum <r...@xenomai.org>",
+};
+
+static struct rtdm_device device = {
+       .class = &rtipc,
+       .label = "rtipc",
 };
 
 int __init __rtipc_init(void)
diff --git a/kernel/drivers/serial/16550A.c b/kernel/drivers/serial/16550A.c
index 7b869f2..2d78c78 100644
--- a/kernel/drivers/serial/16550A.c
+++ b/kernel/drivers/serial/16550A.c
@@ -125,7 +125,6 @@ static unsigned long irqtype[MAX_DEVICES] = {
 };
 static unsigned int baud_base[MAX_DEVICES];
 static int tx_fifo[MAX_DEVICES];
-static unsigned int start_index;
 
 module_param_array(irq, uint, NULL, 0400);
 module_param_array(baud_base, uint, NULL, 0400);
@@ -136,9 +135,6 @@ MODULE_PARM_DESC(baud_base, "Maximum baud rate of the 
serial device "
                 "(internal clock rate / 16)");
 MODULE_PARM_DESC(tx_fifo, "Transmitter FIFO size");
 
-module_param(start_index, uint, 0400);
-MODULE_PARM_DESC(start_index, "First device instance number to be used");
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("jan.kis...@web.de");
 
@@ -313,7 +309,7 @@ static int rt_16550_set_config(struct rt_16550_context *ctx,
        rtdm_lock_get_irqsave(&ctx->lock, lock_ctx);
 
        if (config->config_mask & RTSER_SET_BAUD) {
-               int dev_id = rtdm_fd_device(rtdm_private_to_fd(ctx))->device_id;
+               int dev_id = rtdm_fd_minor(rtdm_private_to_fd(ctx));
                int baud_div;
 
                ctx->config.baud_rate = config->baud_rate;
@@ -441,7 +437,7 @@ void rt_16550_cleanup_ctx(struct rt_16550_context *ctx)
 int rt_16550_open(struct rtdm_fd *fd, int oflags)
 {
        struct rt_16550_context *ctx;
-       int dev_id = rtdm_fd_device(fd)->device_id;
+       int dev_id = rtdm_fd_minor(fd);
        int err;
        uint64_t *dummy;
        rtdm_lockctx_t lock_ctx;
@@ -479,7 +475,7 @@ int rt_16550_open(struct rtdm_fd *fd, int oflags)
 
        err = rtdm_irq_request(&ctx->irq_handle, irq[dev_id],
                        rt_16550_interrupt, irqtype[dev_id],
-                       rtdm_fd_device(fd)->proc_name, ctx);
+                       rtdm_fd_device(fd)->name, ctx);
        if (err) {
                /* reset DTR and RTS */
                rt_16550_reg_out(rt_16550_io_mode_from_ctx(ctx), ctx->base_addr,
@@ -584,7 +580,7 @@ int rt_16550_ioctl(struct rtdm_fd *fd, unsigned int 
request, void *arg)
 
                if ((config->config_mask & RTSER_SET_BAUD) &&
                    (config->baud_rate >
-                           baud_base[rtdm_fd_device(fd)->device_id] ||
+                           baud_base[rtdm_fd_minor(fd)] ||
                            config->baud_rate <= 0))
                        /* invalid baudrate for this port */
                        return -EINVAL;
@@ -1068,11 +1064,14 @@ ssize_t rt_16550_write(struct rtdm_fd *fd, const void 
*buf, size_t nbyte)
        return ret;
 }
 
-static const struct rtdm_device __initdata device_tmpl = {
-       .struct_version         = RTDM_DEVICE_STRUCT_VER,
+static struct rtdm_device_class uart16550A = {
+       .profile_info           = RTDM_PROFILE_INFO(uart16550A,
+                                                   RTDM_CLASS_SERIAL,
+                                                   RTDM_SUBCLASS_16550A,
+                                                   RTSER_PROFILE_VER),
        .device_flags           = RTDM_NAMED_DEVICE | RTDM_EXCLUSIVE,
+       .device_count           = MAX_DEVICES,
        .context_size           = sizeof(struct rt_16550_context),
-       .device_name            = "",
        .ops = {
                .open           = rt_16550_open,
                .close          = rt_16550_close,
@@ -1081,9 +1080,6 @@ static const struct rtdm_device __initdata device_tmpl = {
                .read_rt        = rt_16550_read,
                .write_rt       = rt_16550_write,
        },
-       .device_class           = RTDM_CLASS_SERIAL,
-       .device_sub_class       = RTDM_SUBCLASS_16550A,
-       .profile_version        = RTSER_PROFILE_VER,
        .driver_name            = RT_16550_DRIVER_NAME,
        .driver_version         = RTDM_DRIVER_VER(1, 5, 2),
        .peripheral_name        = "UART 16550A",
@@ -1096,6 +1092,7 @@ int __init rt_16550_init(void)
 {
        struct rtdm_device *dev;
        unsigned long base;
+       char *name;
        int mode;
        int err;
        int i;
@@ -1114,19 +1111,18 @@ int __init rt_16550_init(void)
                if (!irq[i] || !rt_16550_addr_param_valid(i))
                        goto cleanup_out;
 
-               dev = kmalloc(sizeof(struct rtdm_device), GFP_KERNEL);
+               dev = kmalloc(sizeof(struct rtdm_device) +
+                             RTDM_MAX_DEVNAME_LEN, GFP_KERNEL);
                err = -ENOMEM;
                if (!dev)
                        goto cleanup_out;
 
-               memcpy(dev, &device_tmpl, sizeof(struct rtdm_device));
-               ksformat(dev->device_name, RTDM_MAX_DEVNAME_LEN, "rtser%d",
-                        start_index + i);
-               dev->device_id = i;
-
-               dev->proc_name = dev->device_name;
+               dev->class = &uart16550A;
+               dev->label = "rtser%d";
+               name = (char *)(dev + 1);
+               ksformat(name, RTDM_MAX_DEVNAME_LEN, dev->label, i);
 
-               err = rt_16550_init_io(i, dev->device_name);
+               err = rt_16550_init_io(i, name);
                if (err)
                        goto kfree_out;
 
diff --git a/kernel/drivers/serial/mpc52xx_uart.c 
b/kernel/drivers/serial/mpc52xx_uart.c
index b960a7f..6e4f39b 100644
--- a/kernel/drivers/serial/mpc52xx_uart.c
+++ b/kernel/drivers/serial/mpc52xx_uart.c
@@ -1330,7 +1330,6 @@ static int rt_mpc52xx_uart_of_probe(struct 
platform_device *op)
        memcpy(dev, &device_tmpl, sizeof(struct rtdm_device));
        ksformat(dev->device_name, RTDM_MAX_DEVNAME_LEN, "rtserPSC%d",
                 idx);
-       dev->device_id = idx;
        dev->proc_name = dev->device_name;
        dev->device_data = port;
 
diff --git a/kernel/drivers/serial/rt_imx_uart.c 
b/kernel/drivers/serial/rt_imx_uart.c
index 1d547a9..8a04359 100644
--- a/kernel/drivers/serial/rt_imx_uart.c
+++ b/kernel/drivers/serial/rt_imx_uart.c
@@ -1426,7 +1426,6 @@ static int rt_imx_uart_probe(struct platform_device *pdev)
        memcpy(dev, &device_tmpl, sizeof(struct rtdm_device));
        ksformat(dev->device_name, RTDM_MAX_DEVNAME_LEN, "rtser%d",
                 start_index + pdev->id);
-       dev->device_id = pdev->id;
        dev->device_data = port;
 
        dev->proc_name = dev->device_name;
diff --git a/kernel/drivers/testing/rtdmtest.c 
b/kernel/drivers/testing/rtdmtest.c
index 849a0eb..2e671ba 100644
--- a/kernel/drivers/testing/rtdmtest.c
+++ b/kernel/drivers/testing/rtdmtest.c
@@ -21,11 +21,6 @@
 #include <rtdm/driver.h>
 #include <rtdm/testing.h>
 
-static unsigned int start_index;
-
-module_param(start_index, uint, 0400);
-MODULE_PARM_DESC(start_index, "First device instance number to be used");
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("jan.kis...@web.de");
 
@@ -105,56 +100,52 @@ rtdm_test_ioctl(struct rtdm_fd *fd, unsigned int request, 
void __user *arg)
        return err;
 }
 
-static struct rtdm_device device[2] = { [0 ... 1] = {
-       .struct_version         = RTDM_DEVICE_STRUCT_VER,
+static struct rtdm_device_class rtdmtest = {
+       .profile_info           = RTDM_PROFILE_INFO(rtdmtest,
+                                                   RTDM_CLASS_TESTING,
+                                                   RTDM_SUBCLASS_RTDMTEST,
+                                                   RTTST_PROFILE_VER),
        .device_flags           = RTDM_NAMED_DEVICE | RTDM_EXCLUSIVE,
+       .device_count           = 2,
        .context_size           = sizeof(struct rtdm_test_context),
-       .device_name            = "",
        .ops = {
                .open           = rtdm_test_open,
                .close          = rtdm_test_close,
                .ioctl_rt       = rtdm_test_ioctl,
                .ioctl_nrt      = rtdm_test_ioctl,
        },
-       .device_class           = RTDM_CLASS_TESTING,
-       .device_sub_class       = RTDM_SUBCLASS_RTDMTEST,
-       .profile_version        = RTTST_PROFILE_VER,
-       .driver_name            = "xeno_rtdmtest",
+       .driver_name            = "rtdmtest",
        .driver_version         = RTDM_DRIVER_VER(0, 1, 0),
        .peripheral_name        = "RTDM unit test",
        .provider_name          = "Jan Kiszka",
-} };
+};
+
+static struct rtdm_device device[2] = {
+       [0 ... 1] = {
+               .class = &rtdmtest,
+               .label = "rttest-rtdm%d",
+       }
+};
 
 static int __init __rtdm_test_init(void)
 {
-       int dev = 0;
-       int err;
+       int i, ret;
 
        if (!realtime_core_enabled())
                return -ENODEV;
 
-       while (1) {
-               device[dev].proc_name = device[dev].device_name;
-
-               ksformat(device[dev].device_name, RTDM_MAX_DEVNAME_LEN,
-                        "rttest-rtdm%d",
-                        start_index);
-               err = rtdm_dev_register(&device[dev]);
-
-               start_index++;
-
-               if (!err) {
-                       if (++dev >= ARRAY_SIZE(device))
-                               break;
-               } else if (err != -EEXIST) {
-                       while (dev > 0) {
-                               dev--;
-                               rtdm_dev_unregister(&device[dev], 1000);
-                       }
-                       return err;
-               }
+       for (i = 0; i < ARRAY_SIZE(device); i++) {
+               ret = rtdm_dev_register(device + i);
+               if (ret)
+                       goto fail;
        }
+
        return 0;
+fail:
+       while (i-- > 0)
+               rtdm_dev_unregister(device + i, 1000);
+
+       return ret;
 }
 
 static void __exit __rtdm_test_exit(void)
@@ -162,7 +153,7 @@ static void __exit __rtdm_test_exit(void)
        int i;
 
        for (i = 0; i < ARRAY_SIZE(device); i++)
-               rtdm_dev_unregister(&device[i], 1000);
+               rtdm_dev_unregister(device + i, 1000);
 }
 
 module_init(__rtdm_test_init);
diff --git a/kernel/drivers/testing/switchtest.c 
b/kernel/drivers/testing/switchtest.c
index c66dca5..f32782d 100644
--- a/kernel/drivers/testing/switchtest.c
+++ b/kernel/drivers/testing/switchtest.c
@@ -26,6 +26,8 @@
 #include <rtdm/driver.h>
 #include <asm/xenomai/fptest.h>
 
+#define NR_DEVICES  4
+
 #define RTSWITCH_RT      0x10000
 #define RTSWITCH_NRT     0
 #define RTSWITCH_KERNEL  0x20000
@@ -57,11 +59,6 @@ struct rtswitch_context {
        rtdm_nrtsig_t wake_utask;
 };
 
-static unsigned int start_index;
-
-module_param(start_index, uint, 0400);
-MODULE_PARM_DESC(start_index, "First device instance number to be used");
-
 static int fp_features;
 
 MODULE_LICENSE("GPL");
@@ -720,52 +717,65 @@ static int rtswitch_ioctl_rt(struct rtdm_fd *fd,
        }
 }
 
-static struct rtdm_device device = {
-       .struct_version = RTDM_DEVICE_STRUCT_VER,
+static struct rtdm_device_class switchtest = {
+       .profile_info = RTDM_PROFILE_INFO(switchtest,
+                                         RTDM_CLASS_TESTING,
+                                         RTDM_SUBCLASS_SWITCHTEST,
+                                         RTTST_PROFILE_VER),
        .device_flags = RTDM_NAMED_DEVICE,
+       .device_count = 1,
        .context_size = sizeof(struct rtswitch_context),
-       .device_name = "",
        .ops = {
                .open = rtswitch_open,
                .close = rtswitch_close,
                .ioctl_rt = rtswitch_ioctl_rt,
                .ioctl_nrt = rtswitch_ioctl_nrt,
        },
-       .device_class = RTDM_CLASS_TESTING,
-       .device_sub_class = RTDM_SUBCLASS_SWITCHTEST,
-       .profile_version = RTTST_PROFILE_VER,
-       .driver_name = "xeno_switchtest",
+       .driver_name = "switchtest",
        .driver_version = RTDM_DRIVER_VER(0, 1, 1),
        .peripheral_name = "Context Switch Test",
        .provider_name = "Gilles Chanteperdrix",
-       .proc_name = device.device_name,
+};
+
+static struct rtdm_device devices[NR_DEVICES] = {
+       [ 0 ... NR_DEVICES - 1] = {
+               .class = &switchtest,
+               .label = "switchtest%d",
+       },
 };
 
 int __init __switchtest_init(void)
 {
-       int err;
+       int minor, ret;
 
        if (!realtime_core_enabled())
                return 0;
 
        fp_features = fp_detect();
 
-       do {
-               ksformat(device.device_name, RTDM_MAX_DEVNAME_LEN,
-                        "rttest-switchtest%d",
-                        start_index);
-               err = rtdm_dev_register(&device);
+       for (minor = 0; minor < NR_DEVICES; minor++) {
+               ret = rtdm_dev_register(devices + minor);
+               if (ret)
+                       goto fail;
+       }
 
-               start_index++;
-       } while (err == -EEXIST);
+       return 0;
+fail:
+       while (minor-- > 0)
+               rtdm_dev_unregister(devices + minor, 0);
 
-       return err;
+       return ret;
 }
 
 void __switchtest_exit(void)
 {
-       if (realtime_core_enabled())
-               rtdm_dev_unregister(&device, 1000);
+       int minor;
+
+       if (!realtime_core_enabled())
+               return;
+
+       for (minor = 0; minor < NR_DEVICES; minor++)
+               rtdm_dev_unregister(devices + minor, 1000);
 }
 
 module_init(__switchtest_init);
diff --git a/kernel/drivers/testing/timerbench.c 
b/kernel/drivers/testing/timerbench.c
index e244104..644177b 100644
--- a/kernel/drivers/testing/timerbench.c
+++ b/kernel/drivers/testing/timerbench.c
@@ -24,6 +24,8 @@
 #include <rtdm/testing.h>
 #include <rtdm/driver.h>
 
+#define NR_DEVICES  4
+
 struct rt_tmbench_context {
        int mode;
        unsigned long period;
@@ -50,11 +52,6 @@ struct rt_tmbench_context {
        struct semaphore nrt_mutex;
 };
 
-static unsigned int start_index;
-
-module_param(start_index, uint, 0400);
-MODULE_PARM_DESC(start_index, "First device instance number to be used");
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("jan.kis...@web.de");
 
@@ -296,7 +293,7 @@ static int rt_tmbench_start(struct rtdm_fd *fd,
                        ctx->mode = RTTST_TMBENCH_TASK;
        } else {
                rtdm_timer_init(&ctx->timer, timer_proc,
-                               rtdm_fd_device(fd)->device_name);
+                               rtdm_fd_device(fd)->name);
 
                ctx->curr.test_loops = 0;
 
@@ -453,50 +450,63 @@ static int rt_tmbench_ioctl_rt(struct rtdm_fd *fd,
        return err;
 }
 
-static struct rtdm_device device = {
-       .struct_version         = RTDM_DEVICE_STRUCT_VER,
+static struct rtdm_device_class timerbench = {
+       .profile_info           = RTDM_PROFILE_INFO(timerbench,
+                                                   RTDM_CLASS_TESTING,
+                                                   RTDM_SUBCLASS_TIMERBENCH,
+                                                   RTTST_PROFILE_VER),
        .device_flags           = RTDM_NAMED_DEVICE,
+       .device_count           = 1,
        .context_size           = sizeof(struct rt_tmbench_context),
-       .device_name            = "",
        .ops = {
                .open           = rt_tmbench_open,
                .close          = rt_tmbench_close,
                .ioctl_rt       = rt_tmbench_ioctl_rt,
                .ioctl_nrt      = rt_tmbench_ioctl_nrt,
        },
-       .device_class           = RTDM_CLASS_TESTING,
-       .device_sub_class       = RTDM_SUBCLASS_TIMERBENCH,
-       .profile_version        = RTTST_PROFILE_VER,
-       .driver_name            = "xeno_timerbench",
+       .driver_name            = "timerbench",
        .driver_version         = RTDM_DRIVER_VER(0, 2, 1),
        .peripheral_name        = "Timer Latency Benchmark",
        .provider_name          = "Jan Kiszka",
-       .proc_name              = device.device_name,
+};
+
+static struct rtdm_device devices[NR_DEVICES] = {
+       [ 0 ... NR_DEVICES - 1] = {
+               .class = &timerbench,
+               .label = "timerbench%d",
+       },
 };
 
 static int __init __timerbench_init(void)
 {
-       int err;
+       int minor, ret;
 
        if (!realtime_core_enabled())
                return 0;
 
-       do {
-               ksformat(device.device_name, RTDM_MAX_DEVNAME_LEN,
-                        "rttest-timerbench%d",
-                        start_index);
-               err = rtdm_dev_register(&device);
+       for (minor = 0; minor < NR_DEVICES; minor++) {
+               ret = rtdm_dev_register(devices + minor);
+               if (ret)
+                       goto fail;
+       }
 
-               start_index++;
-       } while (err == -EEXIST);
+       return 0;
+fail:
+       while (minor-- > 0)
+               rtdm_dev_unregister(devices + minor, 0);
 
-       return err;
+       return ret;
 }
 
 static void __timerbench_exit(void)
 {
-       if (realtime_core_enabled())
-               rtdm_dev_unregister(&device, 1000);
+       int minor;
+
+       if (!realtime_core_enabled())
+               return;
+
+       for (minor = 0; minor < NR_DEVICES; minor++)
+               rtdm_dev_unregister(devices + minor, 1000);
 }
 
 module_init(__timerbench_init);
diff --git a/kernel/drivers/udd/udd.c b/kernel/drivers/udd/udd.c
index 4bcec17..894e3f5 100644
--- a/kernel/drivers/udd/udd.c
+++ b/kernel/drivers/udd/udd.c
@@ -280,30 +280,31 @@ static inline int check_memregion(struct udd_device *udd,
 
 static inline int register_mapper(struct udd_device *udd)
 {
-       struct rtdm_device *dev = &udd->__reserved.mapper;
        struct udd_reserved *ur = &udd->__reserved;
+       struct rtdm_device *dev = &ur->mapper;
+       struct rtdm_device_class *class = &ur->mapper_class;
 
-       ur->mapper_name = kasformat("%s,mapper", udd->device_name);
+       ur->mapper_name = kasformat("%s,mapper%%d", udd->device_name);
        if (ur->mapper_name == NULL)
                return -ENOMEM;
 
-       memset(dev, 0, sizeof(*dev));
-       dev->struct_version = RTDM_DEVICE_STRUCT_VER;
-       dev->device_flags = RTDM_NAMED_DEVICE|RTDM_MINOR;
-       dev->context_size = 0;
-       dev->ops = (struct rtdm_fd_ops){
-               .open = mapper_open,
-               .close = mapper_close,
-               .mmap = mapper_mmap,
+       class->profile_info = (struct rtdm_profile_info)
+               RTDM_PROFILE_INFO("mapper", RTDM_CLASS_MEMORY,
+                                 RTDM_SUBCLASS_GENERIC, 0);
+       class->device_flags = RTDM_NAMED_DEVICE|RTDM_MINOR;
+       class->device_count = UDD_NR_MAPS;
+       class->ops = (struct rtdm_fd_ops){
+               .open           =       mapper_open,
+               .close          =       mapper_close,
+               .mmap           =       mapper_mmap,
        };
-       dev->device_class = RTDM_CLASS_MEMORY;
-       dev->device_sub_class = RTDM_SUBCLASS_GENERIC;
-       knamecpy(dev->device_name, ur->mapper_name);
-       dev->driver_name = "mapper";
-       dev->driver_version = RTDM_DRIVER_VER(1, 0, 0);
-       dev->peripheral_name = "UDD mapper";
-       dev->proc_name = ur->mapper_name;
-       dev->provider_name = "Philippe Gerum <r...@xenomai.org>";
+       class->driver_name = "udd";
+       class->driver_version = RTDM_DRIVER_VER(1, 0, 0);
+       class->peripheral_name = "UDD mapper";
+       class->provider_name = "Philippe Gerum <r...@xenomai.org>";
+       
+       dev->class = class;
+       dev->label = ur->mapper_name;
 
        return rtdm_dev_register(dev);
 }
@@ -340,6 +341,7 @@ int udd_register_device(struct udd_device *udd)
 {
        struct rtdm_device *dev = &udd->__reserved.device;
        struct udd_reserved *ur = &udd->__reserved;
+       struct rtdm_device_class *class = &ur->class;
        int ret, n;
 
        if (!realtime_core_enabled())
@@ -357,11 +359,13 @@ int udd_register_device(struct udd_device *udd)
                        return ret;
        }
 
-       memset(dev, 0, sizeof(*dev));
-       dev->struct_version = RTDM_DEVICE_STRUCT_VER;
-       dev->device_flags = RTDM_NAMED_DEVICE|udd->device_flags;
-       dev->context_size = sizeof(struct udd_context);
-       dev->ops = (struct rtdm_fd_ops){
+       class->profile_info = (struct rtdm_profile_info)
+               RTDM_PROFILE_INFO(udd->device_name, RTDM_CLASS_UDD,
+                                 udd->device_subclass, 0);
+       class->device_flags = RTDM_NAMED_DEVICE|udd->device_flags;
+       class->device_count = 1;
+       class->context_size = sizeof(struct udd_context);
+       class->ops = (struct rtdm_fd_ops){
                .open = udd_open,
                .ioctl_rt = udd_ioctl_rt,
                .read_rt = udd_read_rt,
@@ -369,19 +373,22 @@ int udd_register_device(struct udd_device *udd)
                .close = udd_close,
                .select = udd_select,
        };
-       dev->device_class = RTDM_CLASS_UDD;
-       dev->device_sub_class = udd->device_subclass;
-       knamecpy(dev->device_name, udd->device_name);
-       dev->driver_name = "udd";
-       dev->driver_version = udd->driver_version;
-       dev->peripheral_name = udd->device_description;
-       dev->proc_name = udd->device_name;
-       dev->provider_name = udd->driver_author;
+       class->driver_name = "udd";
+       class->driver_version = udd->driver_version;
+       class->peripheral_name = udd->device_description;
+       class->provider_name = udd->driver_author;
+
+       dev->class = class;
+       dev->label = udd->device_name;
+
+       ret = rtdm_dev_register(dev);
+       if (ret)
+               return ret;
 
        if (ur->nr_maps > 0) {
                ret = register_mapper(udd);
                if (ret)
-                       return ret;
+                       goto fail_mapper;
        } else
                ur->mapper_name = NULL;
 
@@ -392,22 +399,19 @@ int udd_register_device(struct udd_device *udd)
        if (udd->irq != UDD_IRQ_NONE && udd->irq != UDD_IRQ_CUSTOM) {
                ret = rtdm_irq_request(&ur->irqh, udd->irq,
                                       udd_irq_handler, 0,
-                                      dev->device_name, udd);
+                                      dev->name, udd);
                if (ret)
                        goto fail_irq_request;
        }
 
-       ret = rtdm_dev_register(&ur->device);
-       if (ret)
-               goto fail_dev_register;
-
        return 0;
 
-fail_dev_register:
-       rtdm_irq_free(&ur->irqh);
 fail_irq_request:
        rtdm_dev_unregister(&ur->mapper, 0);
-       kfree(ur->mapper_name);
+fail_mapper:
+       rtdm_dev_unregister(dev, 0);
+       if (ur->mapper_name)
+               kfree(ur->mapper_name);
 
        return ret;
 }
@@ -591,7 +595,7 @@ struct udd_device *udd_get_device(struct rtdm_fd *fd)
 {
        struct rtdm_device *dev = rtdm_fd_device(fd);
 
-       if (dev->device_class == RTDM_CLASS_MEMORY)
+       if (dev->class->profile_info.class_id == RTDM_CLASS_MEMORY)
                return container_of(dev, struct udd_device, __reserved.mapper);
 
        return container_of(dev, struct udd_device, __reserved.device);


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to