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

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

cobalt/rtdm, kernel/drivers: split device class / instance abstractions

How devices are described for registration with rtdm_dev_register() is
significantly modified, affecting both named and protocol device
drivers exactly the same way. Aside of fixing consistency issues, the
bulk of changes is aimed at narrowing the gap between the regular
Linux device driver model and RTDM.

RTDM now shares the Linux namespace for named devices, which are
backed by common character device objects from the regular Linux
device model. As a consequence of this, file descriptors obtained on
named RTDM devices are regular file descriptors on real chrdevs,
visible from the /proc/<pid>/fd interface.

The major change required for supporting this closer integration of
RTDM into the regular Linux driver model involved splitting the device
class properties from the device instance definitions, which used to
be combined in Xenomai 2.x into the rtdm_device descriptor.

A new rtdm_device_class descriptor is introduced, for describing the
general static properties of the devices exposed by a
driver. rtdm_device now represents an instance of such class.

rtdm_device objects link to the descriptor of the rtdm_device class
they belong to.

Hotplug support
---------------

RTDM first allocates and reserves a major and a range of device minors
when the first device of a named device class is registered via
rtdm_dev_register(). Up to class->device_count minors will be
reserved. Minor number are assigned to devices in order of
registration, starting from minor #0.

Device nodes for named RTDM devices are automatically visible from the
/dev/rtdm/ hierarchy with hotplug-enabled device fs (DEVTMPFS now
recommended).

---

 include/cobalt/kernel/rtdm/analogy/context.h |    2 +-
 include/cobalt/kernel/rtdm/driver.h          |  202 ++++++++++------
 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                  |  318 +++++++++++++++++---------
 kernel/cobalt/rtdm/drvlib.c                  |   10 +-
 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/Kconfig                |    2 +-
 kernel/drivers/serial/mpc52xx_uart.c         |   59 +++--
 kernel/drivers/serial/rt_imx_uart.c          |   28 +--
 kernel/drivers/testing/rtdmtest.c            |   63 +++--
 kernel/drivers/testing/switchtest.c          |   58 +++--
 kernel/drivers/testing/timerbench.c          |   60 +++--
 kernel/drivers/udd/udd.c                     |   86 +++----
 24 files changed, 789 insertions(+), 578 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..fc0f056 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,158 @@ 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 for composing the device name. A
+        * limited printf-like format string is assumed, with a
+        * provision for replacing the first %d/%i placeholder found
+        * in the string by the device minor number.  It is up to the
+        * driver to actually mention this placeholder or not,
+        * depending on the naming convention for its devices.  For
+        * named devices, the corresponding device node will
+        * automatically appear in the /dev/rtdm hierachy with
+        * hotplug-enabled device filesystems (DEVTMPFS).
+        */
+       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..4727d67 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
  *
- * @param[in] device Pointer to structure describing the device to be
- * unregistered.
+ * The device descriptor removed from the RTDM namespace.
+ *
+ * @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,35 +425,42 @@ 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);
 
        rtdm_proc_unregister_device(device);
 
-       if (handle)
+       if (handle) {
                xnregistry_remove(handle);
+               device_destroy(class->named.kclass,
+                              MKDEV(class->named.major,
+                                    device->named.minor));
+       }
+
+       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/drvlib.c b/kernel/cobalt/rtdm/drvlib.c
index ce104d2..217b55a 100644
--- a/kernel/cobalt/rtdm/drvlib.c
+++ b/kernel/cobalt/rtdm/drvlib.c
@@ -1700,13 +1700,9 @@ int __rtdm_mmap_from_fdop(struct rtdm_fd *fd, size_t 
len, off_t offset,
         * XXX: A .get_unmapped_area handler must be provided in the
         * nommu case. We use this to force the memory management code
         * not to share VM regions for distinct areas to map to, as it
-        * would otherwise do since all requests originate from the
-        * same file (i.e. from /dev/mem, see do_mmap_pgoff() in the
-        * nommu case).
-        *
-        * We could solve this by implementing a virtual filesystem
-        * for RTDM devices, which would go a long way toward a better
-        * integration with the regular device driver model.
+        * would otherwise do since all requests currently apply to
+        * the same file (i.e. from /dev/mem, see do_mmap_pgoff() in
+        * the nommu case).
         */
        if (fd->ops->get_unmapped_area)
                offset = fd->ops->get_unmapped_area(fd, len, 0, flags);
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/Kconfig b/kernel/drivers/serial/Kconfig
index e43fa74..43dd5ec 100644
--- a/kernel/drivers/serial/Kconfig
+++ b/kernel/drivers/serial/Kconfig
@@ -63,7 +63,7 @@ config XENO_DRIVERS_16550A_PCI_MOXA
          CP-168U
 
 config XENO_DRIVERS_MPC52XX_UART
-       depends on XENO_SKIN_RTDM && PPC_MPC52xx
+       depends on PPC_MPC52xx
        tristate "MPC52xx PSC UART driver"
        help
        Real-time UART driver for the PSC on the MPC5200 processor.
diff --git a/kernel/drivers/serial/mpc52xx_uart.c 
b/kernel/drivers/serial/mpc52xx_uart.c
index b960a7f..8386f35 100644
--- a/kernel/drivers/serial/mpc52xx_uart.c
+++ b/kernel/drivers/serial/mpc52xx_uart.c
@@ -331,9 +331,9 @@ static inline int rt_mpc52xx_uart_tx_interrupt(struct 
rt_mpc52xx_uart_ctx *ctx)
                                ctx->mcr_status);
                        psc_set_mcr(ctx, ctx->mcr_status);
                }
-               if ((ctx->config.rs485 ||
-                    (ctx->config.event_mask & RTSER_EVENT_TXEMPTY) &&
-                    (ctx->imr_status & MPC52xx_PSC_IMR_TXEMP) == 0) {
+               if (ctx->config.rs485 ||
+                   ((ctx->config.event_mask & RTSER_EVENT_TXEMPTY) &&
+                    (ctx->imr_status & MPC52xx_PSC_IMR_TXEMP) == 0)) {
                        /* enable tx-empty interrupt */
                        ctx->imr_status |= MPC52xx_PSC_IMR_TXEMP;
                        dev_dbg(ctx->port->dev, "Enable TXEMP interrupt, "
@@ -691,7 +691,7 @@ static int rt_mpc52xx_uart_open(struct rtdm_fd *fd, int 
oflags)
 
        err = rtdm_irq_request(&ctx->irq_handle, ctx->port->irq,
                               rt_mpc52xx_uart_interrupt, 0,
-                              rtdm_fd_device(fd)->proc_name, ctx);
+                              rtdm_fd_device(fd)->name, ctx);
        if (err) {
                psc_set_mcr(ctx, 0);
                rt_mpc52xx_uart_cleanup_ctx(ctx);
@@ -740,7 +740,7 @@ static int rt_mpc52xx_uart_ioctl(struct rtdm_fd *fd,
 
        switch (request) {
        case RTSER_RTIOC_GET_CONFIG:
-               if (rtdm_is_user(fd))
+               if (rtdm_fd_is_user(fd))
                        err = rtdm_safe_copy_to_user(fd, arg,
                                                     &ctx->config,
                                                     sizeof(struct
@@ -756,7 +756,7 @@ static int rt_mpc52xx_uart_ioctl(struct rtdm_fd *fd,
 
                config = (struct rtser_config *)arg;
 
-               if (rtdm_is_user(fd)) {
+               if (rtdm_fd_is_user(fd)) {
                        err = rtdm_safe_copy_from_user(fd, &config_buf,
                                                       arg,
                                                       sizeof(struct
@@ -767,7 +767,7 @@ static int rt_mpc52xx_uart_ioctl(struct rtdm_fd *fd,
                        config = &config_buf;
                }
 
-               if (config->config_mask & RTSER_SET_BAUD) &&
+               if ((config->config_mask & RTSER_SET_BAUD) &&
                    (config->baud_rate <= 0))
                        /* invalid baudrate for this port */
                        return -EINVAL;
@@ -806,7 +806,7 @@ static int rt_mpc52xx_uart_ioctl(struct rtdm_fd *fd,
 
                rtdm_lock_put_irqrestore(&ctx->lock, lock_ctx);
 
-               if (rtdm_is_user(fd)) {
+               if (rtdm_fd_is_user(fd)) {
                        struct rtser_status status_buf;
 
                        status_buf.line_status = status;
@@ -825,7 +825,7 @@ static int rt_mpc52xx_uart_ioctl(struct rtdm_fd *fd,
        }
 
        case RTSER_RTIOC_GET_CONTROL:
-               if (rtdm_is_user(fd))
+               if (rtdm_fd_is_user(fd))
                        err = rtdm_safe_copy_to_user(fd, arg,
                                                     &ctx->mcr_status,
                                                     sizeof(int));
@@ -889,7 +889,7 @@ static int rt_mpc52xx_uart_ioctl(struct rtdm_fd *fd,
 
                rtdm_lock_put_irqrestore(&ctx->lock, lock_ctx);
 
-               if (rtdm_is_user(fd))
+               if (rtdm_fd_is_user(fd))
                        err =
                            rtdm_safe_copy_to_user(fd, arg, &ev,
                                                   sizeof(struct
@@ -969,7 +969,7 @@ static ssize_t rt_mpc52xx_uart_read(struct rtdm_fd *fd, 
void *buf,
        if (nbyte == 0)
                return 0;
 
-       if (rtdm_is_user(fd) && !rtdm_rw_user_ok(fd, buf, nbyte))
+       if (rtdm_fd_is_user(fd) && !rtdm_rw_user_ok(fd, buf, nbyte))
                return -EFAULT;
 
        ctx = rtdm_fd_to_private(fd);
@@ -1012,7 +1012,7 @@ static ssize_t rt_mpc52xx_uart_read(struct rtdm_fd *fd, 
void *buf,
                                   separately. */
                                subblock = IN_BUFFER_SIZE - in_pos;
 
-                               if (rtdm_is_user(fd)) {
+                               if (rtdm_fd_is_user(fd)) {
                                        if (rtdm_copy_to_user
                                            (fd, out_pos,
                                             &ctx->in_buf[in_pos],
@@ -1031,7 +1031,7 @@ static ssize_t rt_mpc52xx_uart_read(struct rtdm_fd *fd, 
void *buf,
                                in_pos = 0;
                        }
 
-                       if (rtdm_is_user(fd)) {
+                       if (rtdm_fd_is_user(fd)) {
                                if (rtdm_copy_to_user(fd, out_pos,
                                                      &ctx->in_buf[in_pos],
                                                      subblock) != 0) {
@@ -1125,7 +1125,7 @@ static ssize_t rt_mpc52xx_uart_write(struct rtdm_fd *fd,
        if (nbyte == 0)
                return 0;
 
-       if (rtdm_is_user(fd) && !rtdm_read_user_ok(fd, buf, nbyte))
+       if (rtdm_fd_is_user(fd) && !rtdm_read_user_ok(fd, buf, nbyte))
                return -EFAULT;
 
        ctx = rtdm_fd_to_private(fd);
@@ -1155,7 +1155,7 @@ static ssize_t rt_mpc52xx_uart_write(struct rtdm_fd *fd,
                                   end separately. */
                                subblock = OUT_BUFFER_SIZE - out_pos;
 
-                               if (rtdm_is_user(fd)) {
+                               if (rtdm_fd_is_user(fd)) {
                                        if (rtdm_copy_from_user
                                            (fd,
                                             &ctx->out_buf[out_pos],
@@ -1174,7 +1174,7 @@ static ssize_t rt_mpc52xx_uart_write(struct rtdm_fd *fd,
                                out_pos = 0;
                        }
 
-                       if (rtdm_is_user(fd)) {
+                       if (rtdm_fd_is_user(fd)) {
                                if (rtdm_copy_from_user
                                    (fd, &ctx->out_buf[out_pos],
                                     in_pos, subblock) != 0) {
@@ -1232,11 +1232,14 @@ static ssize_t rt_mpc52xx_uart_write(struct rtdm_fd *fd,
        return ret;
 }
 
-static const struct rtdm_device device_tmpl = {
-       .struct_version         = RTDM_DEVICE_STRUCT_VER,
+static struct rtdm_device_class mpc52xx_uart = {
+       .profile_info           = RTDM_PROFILE_INFO(imx_uart,
+                                                   RTDM_CLASS_SERIAL,
+                                                   RTDM_SUBCLASS_16550A,
+                                                   RTSER_PROFILE_VER),
+       .device_count           = MPC52xx_PSC_MAXNUM,
        .device_flags           = RTDM_NAMED_DEVICE | RTDM_EXCLUSIVE,
        .context_size           = sizeof(struct rt_mpc52xx_uart_ctx),
-       .device_name            = "",
        .ops = {
                .open           = rt_mpc52xx_uart_open,
                .close          = rt_mpc52xx_uart_close,
@@ -1245,9 +1248,6 @@ static const struct rtdm_device device_tmpl = {
                .read_rt        = rt_mpc52xx_uart_read,
                .write_rt       = rt_mpc52xx_uart_write,
        },
-       .device_class           = RTDM_CLASS_SERIAL,
-       .device_sub_class       = RTDM_SUBCLASS_16550A,
-       .profile_version        = RTSER_PROFILE_VER,
        .driver_name            = RT_MPC52XX_UART_DRVNAM,
        .driver_version         = RTDM_DRIVER_VER(1, 0, 0),
        .peripheral_name        = "MPC52xx UART",
@@ -1327,11 +1327,8 @@ static int rt_mpc52xx_uart_of_probe(struct 
platform_device *op)
                goto out_dispose_irq_mapping;
        }
 
-       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->class = &mpc52xx_uart;
+       dev->label = "rtserPSC%d";
        dev->device_data = port;
 
        rt_mpc52xx_uart_init_hw(port);
@@ -1343,7 +1340,7 @@ static int rt_mpc52xx_uart_of_probe(struct 
platform_device *op)
        dev_set_drvdata(&op->dev, dev);
 
        dev_info(&op->dev, "%s on PSC%d at 0x%p, irq=%d, clk=%i\n",
-                dev->device_name, port->num, port->psc, port->irq,
+                dev->name, port->num, port->psc, port->irq,
                 port->uartclk);
 
        return 0;
@@ -1388,7 +1385,7 @@ static struct of_device_id rt_mpc52xx_uart_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, rt_mpc52xx_uart_of_match);
 
-static struct of_platform_driver rt_mpc52xx_uart_of_driver = {
+static struct platform_driver rt_mpc52xx_uart_of_driver = {
        .probe = rt_mpc52xx_uart_of_probe,
        .remove =  rt_mpc52xx_uart_of_remove,
        .driver = {
@@ -1422,7 +1419,7 @@ static int __init rt_mpc52xx_uart_init(void)
 
        rt_mpc52xx_uart_of_enumerate();
 
-       ret = of_register_platform_driver(&rt_mpc52xx_uart_of_driver);
+       ret = platform_driver_register(&rt_mpc52xx_uart_of_driver);
        if (ret) {
                printk(KERN_ERR
                       "%s; Could not register  driver (err=%d)\n",
@@ -1436,7 +1433,7 @@ static int __init rt_mpc52xx_uart_init(void)
 static void __exit rt_mpc52xx_uart_exit(void)
 {
        if (realtime_core_enabled())
-               of_unregister_platform_driver(&rt_mpc52xx_uart_of_driver);
+               platform_driver_unregister(&rt_mpc52xx_uart_of_driver);
 }
 
 module_init(rt_mpc52xx_uart_init);
diff --git a/kernel/drivers/serial/rt_imx_uart.c 
b/kernel/drivers/serial/rt_imx_uart.c
index 1d547a9..af7e903 100644
--- a/kernel/drivers/serial/rt_imx_uart.c
+++ b/kernel/drivers/serial/rt_imx_uart.c
@@ -187,10 +187,6 @@ static int tx_fifo[RT_IMX_UART_MAX];
 compat_module_param_array(tx_fifo, int, RT_IMX_UART_MAX, 0400);
 MODULE_PARM_DESC(tx_fifo, "Transmitter FIFO size");
 
-static unsigned int start_index;
-module_param(start_index, uint, 0400);
-MODULE_PARM_DESC(start_index, "First device instance number to be used");
-
 struct rt_imx_uart_port {
        unsigned char __iomem *membase; /* read/write[bwl] */
        resource_size_t mapbase;        /* for ioremap */
@@ -792,7 +788,7 @@ static int rt_imx_uart_open(struct rtdm_fd *fd, int oflags)
 
        retval = rtdm_irq_request(&ctx->irq_handle,
                                  port->irq, rt_imx_uart_int, 0,
-                                 rtdm_fd_device(fd)->proc_name, ctx);
+                                 rtdm_fd_device(fd)->name, ctx);
        if (retval)
                return retval;
 
@@ -1363,11 +1359,14 @@ static ssize_t rt_imx_uart_write(struct rtdm_fd *fd, 
const void *buf,
        return ret;
 }
 
-static const struct rtdm_device __initdata device_tmpl = {
-       .struct_version         = RTDM_DEVICE_STRUCT_VER,
+static struct rtdm_device imx_uart = {
+       .profile_info           = RTDM_PROFILE_INFO(imx_uart,
+                                                   RTDM_CLASS_SERIAL,
+                                                   RTDM_SUBCLASS_16550A,
+                                                   RTSER_PROFILE_VER),
+       .device_count           = RT_IMX_UART_MAX,
        .device_flags           = RTDM_NAMED_DEVICE | RTDM_EXCLUSIVE,
        .context_size           = sizeof(struct rt_imx_uart_ctx),
-       .device_name            = "",
        .ops = {
                .open           = rt_imx_uart_open,
                .close          = rt_imx_uart_close,
@@ -1376,9 +1375,6 @@ static const struct rtdm_device __initdata device_tmpl = {
                .read_rt        = rt_imx_uart_read,
                .write_rt       = rt_imx_uart_write,
        },
-       .device_class           = RTDM_CLASS_SERIAL,
-       .device_sub_class       = RTDM_SUBCLASS_16550A,
-       .profile_version        = RTSER_PROFILE_VER,
        .driver_name            = DRIVER_NAME,
        .driver_version         = RTDM_DRIVER_VER(1, 0, 0),
        .peripheral_name        = "IMX UART",
@@ -1423,14 +1419,10 @@ static int rt_imx_uart_probe(struct platform_device 
*pdev)
 
 
        dev = &port->rtdm_dev;
-       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->class = &imx_uart;
+       dev->label = "rtser%d";
        dev->device_data = port;
 
-       dev->proc_name = dev->device_name;
-
        if (!tx_fifo[pdev->id] || tx_fifo[pdev->id] > TX_FIFO_SIZE)
                port->tx_fifo = TX_FIFO_SIZE;
        else
@@ -1465,7 +1457,7 @@ static int rt_imx_uart_probe(struct platform_device *pdev)
 
        printk(KERN_INFO
               "%s on IMX UART%d: membase=0x%p mapbase=%#x irq=%d uartclk=%d\n",
-              dev->device_name, pdev->id, port->membase, (u32)port->mapbase,
+              dev->name, pdev->id, port->membase, (u32)port->mapbase,
               port->irq, port->uartclk);
 
        return 0;
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