[PATCH 009/111] DRVMGR: added driver manager to cpukit/libdrvmgr

Daniel Hellstrom daniel at gaisler.com
Thu Feb 26 16:38:11 UTC 2015


---
 aclocal/enable-drvmgr.m4                     |   12 +
 c/src/aclocal/enable-drvmgr.m4               |   12 +
 c/src/lib/libbsp/shared/bspdriverlevelhook.c |   16 +
 c/src/lib/libbsp/shared/include/bootcard.h   |    2 +
 c/src/make/configure.ac                      |    1 +
 configure.ac                                 |    1 +
 cpukit/Makefile.am                           |    7 +
 cpukit/aclocal/enable-drvmgr.m4              |   12 +
 cpukit/configure.ac                          |    7 +
 cpukit/libdrvmgr/Makefile.am                 |   33 +
 cpukit/libdrvmgr/README                      |  112 +++
 cpukit/libdrvmgr/drvmgr.c                    |  643 +++++++++++++++++
 cpukit/libdrvmgr/drvmgr.h                    |  965 ++++++++++++++++++++++++++
 cpukit/libdrvmgr/drvmgr_by_id.c              |   33 +
 cpukit/libdrvmgr/drvmgr_by_name.c            |   37 +
 cpukit/libdrvmgr/drvmgr_confdefs.h           |   86 +++
 cpukit/libdrvmgr/drvmgr_dev_by_name.c        |   34 +
 cpukit/libdrvmgr/drvmgr_drvinf.c             |  148 ++++
 cpukit/libdrvmgr/drvmgr_for_each_dev.c       |  104 +++
 cpukit/libdrvmgr/drvmgr_for_each_list_dev.c  |   44 ++
 cpukit/libdrvmgr/drvmgr_func.c               |   42 ++
 cpukit/libdrvmgr/drvmgr_func_call.c          |   21 +
 cpukit/libdrvmgr/drvmgr_init.c               |   26 +
 cpukit/libdrvmgr/drvmgr_internal.h           |   70 ++
 cpukit/libdrvmgr/drvmgr_list.c               |   67 ++
 cpukit/libdrvmgr/drvmgr_list.h               |   79 +++
 cpukit/libdrvmgr/drvmgr_lock.c               |   38 +
 cpukit/libdrvmgr/drvmgr_print.c              |  457 ++++++++++++
 cpukit/libdrvmgr/drvmgr_res.c                |  102 +++
 cpukit/libdrvmgr/drvmgr_rw.c                 |   52 ++
 cpukit/libdrvmgr/drvmgr_translate.c          |  149 ++++
 cpukit/libdrvmgr/drvmgr_translate_check.c    |   35 +
 cpukit/libdrvmgr/drvmgr_unregister.c         |  186 +++++
 cpukit/preinstall.am                         |   17 +
 cpukit/sapi/include/confdefs.h               |   11 +-
 cpukit/sapi/src/exinit.c                     |   63 ++
 cpukit/wrapup/Makefile.am                    |    3 +-
 37 files changed, 3724 insertions(+), 3 deletions(-)
 create mode 100644 aclocal/enable-drvmgr.m4
 create mode 100644 c/src/aclocal/enable-drvmgr.m4
 create mode 100644 c/src/lib/libbsp/shared/bspdriverlevelhook.c
 create mode 100644 cpukit/aclocal/enable-drvmgr.m4
 create mode 100644 cpukit/libdrvmgr/Makefile.am
 create mode 100644 cpukit/libdrvmgr/README
 create mode 100644 cpukit/libdrvmgr/drvmgr.c
 create mode 100644 cpukit/libdrvmgr/drvmgr.h
 create mode 100644 cpukit/libdrvmgr/drvmgr_by_id.c
 create mode 100644 cpukit/libdrvmgr/drvmgr_by_name.c
 create mode 100644 cpukit/libdrvmgr/drvmgr_confdefs.h
 create mode 100644 cpukit/libdrvmgr/drvmgr_dev_by_name.c
 create mode 100644 cpukit/libdrvmgr/drvmgr_drvinf.c
 create mode 100644 cpukit/libdrvmgr/drvmgr_for_each_dev.c
 create mode 100644 cpukit/libdrvmgr/drvmgr_for_each_list_dev.c
 create mode 100644 cpukit/libdrvmgr/drvmgr_func.c
 create mode 100644 cpukit/libdrvmgr/drvmgr_func_call.c
 create mode 100644 cpukit/libdrvmgr/drvmgr_init.c
 create mode 100644 cpukit/libdrvmgr/drvmgr_internal.h
 create mode 100644 cpukit/libdrvmgr/drvmgr_list.c
 create mode 100644 cpukit/libdrvmgr/drvmgr_list.h
 create mode 100644 cpukit/libdrvmgr/drvmgr_lock.c
 create mode 100644 cpukit/libdrvmgr/drvmgr_print.c
 create mode 100644 cpukit/libdrvmgr/drvmgr_res.c
 create mode 100644 cpukit/libdrvmgr/drvmgr_rw.c
 create mode 100644 cpukit/libdrvmgr/drvmgr_translate.c
 create mode 100644 cpukit/libdrvmgr/drvmgr_translate_check.c
 create mode 100644 cpukit/libdrvmgr/drvmgr_unregister.c

diff --git a/aclocal/enable-drvmgr.m4 b/aclocal/enable-drvmgr.m4
new file mode 100644
index 0000000..489f60e
--- /dev/null
+++ b/aclocal/enable-drvmgr.m4
@@ -0,0 +1,12 @@
+AC_DEFUN([RTEMS_ENABLE_DRVMGR],
+[
+## AC_BEFORE([$0], [RTEMS_CHECK_DRVMGR_STARTUP])dnl
+
+AC_ARG_ENABLE(drvmgr,
+[AS_HELP_STRING([--enable-drvmgr],[enable Driver Manager at Startup])],
+[case "${enableval}" in 
+  yes) RTEMS_DRVMGR_STARTUP=yes ;;
+  no) RTEMS_DRVMGR_STARTUP=no ;;
+  *)  AC_MSG_ERROR(bad value ${enableval} for enable-drvmgr option) ;;
+esac],[RTEMS_DRVMGR_STARTUP=yes]) 
+])
diff --git a/c/src/aclocal/enable-drvmgr.m4 b/c/src/aclocal/enable-drvmgr.m4
new file mode 100644
index 0000000..489f60e
--- /dev/null
+++ b/c/src/aclocal/enable-drvmgr.m4
@@ -0,0 +1,12 @@
+AC_DEFUN([RTEMS_ENABLE_DRVMGR],
+[
+## AC_BEFORE([$0], [RTEMS_CHECK_DRVMGR_STARTUP])dnl
+
+AC_ARG_ENABLE(drvmgr,
+[AS_HELP_STRING([--enable-drvmgr],[enable Driver Manager at Startup])],
+[case "${enableval}" in 
+  yes) RTEMS_DRVMGR_STARTUP=yes ;;
+  no) RTEMS_DRVMGR_STARTUP=no ;;
+  *)  AC_MSG_ERROR(bad value ${enableval} for enable-drvmgr option) ;;
+esac],[RTEMS_DRVMGR_STARTUP=yes]) 
+])
diff --git a/c/src/lib/libbsp/shared/bspdriverlevelhook.c b/c/src/lib/libbsp/shared/bspdriverlevelhook.c
new file mode 100644
index 0000000..93406f9
--- /dev/null
+++ b/c/src/lib/libbsp/shared/bspdriverlevelhook.c
@@ -0,0 +1,16 @@
+/*
+ *  This is a dummy bsp_driver_level_hook routine.
+ *
+ *  COPYRIGHT (c) 2015.
+ *  Cobham Gaisler.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp/bootcard.h>
+
+void bsp_driver_level_hook( int level )
+{
+}
diff --git a/c/src/lib/libbsp/shared/include/bootcard.h b/c/src/lib/libbsp/shared/include/bootcard.h
index 5e31fcf..c394602 100644
--- a/c/src/lib/libbsp/shared/include/bootcard.h
+++ b/c/src/lib/libbsp/shared/include/bootcard.h
@@ -57,6 +57,8 @@ void bsp_pretasking_hook(void);
 
 void bsp_predriver_hook(void);
 
+void bsp_driver_level_hook( int level );
+
 void bsp_postdriver_hook(void);
 
 void bsp_reset(void);
diff --git a/c/src/make/configure.ac b/c/src/make/configure.ac
index 08f8c8b..10c47a0 100644
--- a/c/src/make/configure.ac
+++ b/c/src/make/configure.ac
@@ -20,6 +20,7 @@ RTEMS_ENABLE_MULTIPROCESSING
 RTEMS_ENABLE_POSIX
 RTEMS_ENABLE_NETWORKING
 RTEMS_ENABLE_CXX
+RTEMS_ENABLE_DRVMGR
 
 RTEMS_ENV_RTEMSBSP
 
diff --git a/configure.ac b/configure.ac
index 4d6cd56..61e0eda 100644
--- a/configure.ac
+++ b/configure.ac
@@ -28,6 +28,7 @@ RTEMS_ENABLE_RTEMS_DEBUG
 RTEMS_ENABLE_RTEMSBSP
 RTEMS_ENABLE_MULTILIB
 RTEMS_ENABLE_PARAVIRT
+RTEMS_ENABLE_DRVMGR
 
 AC_ARG_ENABLE([docs],
   [AS_HELP_STRING([--enable-docs],[enable building documentation
diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
index 0364bf1..4f98978 100644
--- a/cpukit/Makefile.am
+++ b/cpukit/Makefile.am
@@ -8,6 +8,7 @@ SUBDIRS = . score rtems sapi posix
 SUBDIRS += dev
 SUBDIRS += libcrypt
 SUBDIRS += libcsupport libblock libfs
+SUBDIRS += libdrvmgr
 SUBDIRS += libnetworking librpc
 SUBDIRS += libpci
 SUBDIRS += libi2c
@@ -230,6 +231,12 @@ include_rtems_HEADERS += libmisc/untar/untar.h
 ## fsmount
 include_rtems_HEADERS += libmisc/fsmount/fsmount.h
 
+## Driver manager
+include_drvmgrdir = $(includedir)/drvmgr
+include_drvmgr_HEADERS = libdrvmgr/drvmgr.h
+include_drvmgr_HEADERS += libdrvmgr/drvmgr_confdefs.h
+include_drvmgr_HEADERS += libdrvmgr/drvmgr_list.h
+
 ## HACK: doxygen filter.
 EXTRA_DIST = doxy-filter
 
diff --git a/cpukit/aclocal/enable-drvmgr.m4 b/cpukit/aclocal/enable-drvmgr.m4
new file mode 100644
index 0000000..a9da288
--- /dev/null
+++ b/cpukit/aclocal/enable-drvmgr.m4
@@ -0,0 +1,12 @@
+dnl $Id: enable-drvmgr.m4,v 1.0
+
+AC_DEFUN([RTEMS_ENABLE_DRVMGR],
+[
+AC_ARG_ENABLE(drvmgr,
+AS_HELP_STRING(--enable-drvmgr,enable drvmgr at startup),
+[case "${enableval}" in 
+  yes) RTEMS_DRVMGR_STARTUP=yes ;;
+  no) RTEMS_DRVMGR_STARTUP=no ;;
+  *)  AC_MSG_ERROR(bad value ${enableval} for enable-drvmgr option) ;;
+esac],[RTEMS_DRVMGR_STARTUP=yes]) 
+])
diff --git a/cpukit/configure.ac b/cpukit/configure.ac
index 8042c35..81bbc89 100644
--- a/cpukit/configure.ac
+++ b/cpukit/configure.ac
@@ -17,6 +17,7 @@ RTEMS_ENABLE_RTEMS_DEBUG
 RTEMS_ENABLE_NETWORKING
 RTEMS_ENABLE_PARAVIRT
 RTEMS_ENABLE_PROFILING
+RTEMS_ENABLE_DRVMGR
 
 RTEMS_ENV_RTEMSCPU
 RTEMS_CHECK_RTEMS_DEBUG
@@ -226,6 +227,11 @@ RTEMS_CPUOPT([RTEMS_NETWORKING],
   [1],
   [if networking is enabled])
 
+RTEMS_CPUOPT([RTEMS_DRVMGR_STARTUP],
+  [test x"$enable_drvmgr" = xyes],
+  [1],
+  [if driver manager api is supported])
+
 RTEMS_CPUOPT([RTEMS_VERSION],
   [true],
   ["]_RTEMS_VERSION["],
@@ -428,6 +434,7 @@ score/cpu/v850/Makefile
 score/cpu/no_cpu/Makefile
 posix/Makefile
 libblock/Makefile
+libdrvmgr/Makefile
 libfs/Makefile
 libfs/src/nfsclient/Makefile
 libgnat/Makefile
diff --git a/cpukit/libdrvmgr/Makefile.am b/cpukit/libdrvmgr/Makefile.am
new file mode 100644
index 0000000..d93854a
--- /dev/null
+++ b/cpukit/libdrvmgr/Makefile.am
@@ -0,0 +1,33 @@
+##
+##  $Id: Makefile.am
+##
+
+include $(top_srcdir)/automake/compile.am
+
+EXTRA_DIST=
+
+noinst_LIBRARIES = libdrvmgr.a
+
+libdrvmgr_a_SOURCES = drvmgr.c
+libdrvmgr_a_SOURCES += drvmgr.h
+libdrvmgr_a_SOURCES += drvmgr_by_name.c
+libdrvmgr_a_SOURCES += drvmgr_by_id.c
+libdrvmgr_a_SOURCES += drvmgr_dev_by_name.c
+libdrvmgr_a_SOURCES += drvmgr_drvinf.c
+libdrvmgr_a_SOURCES += drvmgr_init.c
+libdrvmgr_a_SOURCES += drvmgr_confdefs.h
+libdrvmgr_a_SOURCES += drvmgr_for_each_dev.c
+libdrvmgr_a_SOURCES += drvmgr_for_each_list_dev.c
+libdrvmgr_a_SOURCES += drvmgr_func.c
+libdrvmgr_a_SOURCES += drvmgr_func_call.c
+libdrvmgr_a_SOURCES += drvmgr_list.c
+libdrvmgr_a_SOURCES += drvmgr_list.h
+libdrvmgr_a_SOURCES += drvmgr_lock.c
+libdrvmgr_a_SOURCES += drvmgr_print.c
+libdrvmgr_a_SOURCES += drvmgr_res.c
+libdrvmgr_a_SOURCES += drvmgr_rw.c
+libdrvmgr_a_SOURCES += drvmgr_translate.c
+libdrvmgr_a_SOURCES += drvmgr_translate_check.c
+libdrvmgr_a_SOURCES += drvmgr_unregister.c
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/libdrvmgr/README b/cpukit/libdrvmgr/README
new file mode 100644
index 0000000..6e55370
--- /dev/null
+++ b/cpukit/libdrvmgr/README
@@ -0,0 +1,112 @@
+DRIVER MANAGER
+==============
+
+See documentation in Aeroflex Gaisler Driver manual.
+
+
+INITIALIZATION
+==============
+The Driver Manager can be intialized in two different ways:
+ 1. during RTEMS startup
+ 2. started by user, typically in the Init task
+
+The driver manager is initalized during RTEMS startup in the
+rtems_initialize_device_drivers() function when RTEMS is
+configured with driver manager support.
+
+When RTEMS is not configured with the driver manager, the manager
+may still be initialized by the user after system startup, typically
+from the Init() task.
+
+The main difference between the two ways is when interrupt
+is enabled. Interrupt is enabled for the first time by RTEMS when
+the Init task is started. This means, for the first case, that
+drivers can not use interrupt services until after the
+initialization phase is over and the user request services from
+the drivers. For the second case of initialization, this means
+that driver must take extra care during initalization when interrupt
+is enabled so that spurious interrupts are not generated and that the
+system does not hang in an infinite IRQ loop.
+
+Most of the problems above are solved for the two methods by 
+specifying in which initialization levels IRQ handling is done.
+See Level 1 and Level 2 below.
+
+Other differences is that IRQ, System Clock Timer, debug Console
+and Console can be initalized by the help of the driver manager
+when initialized during start up. Between Level0 and Level1 the
+RTEMS I/O Manager drivers are initialized. The LEON3 BSP has
+therefore two different versions of the basic drivers.
+
+
+LEVEL0
+------
+The level of uninitialized devices that have been united with a
+driver.
+
+
+LEVEL1 - FIND/RESET/IRQ Clear
+-----------------------------
+The driver is for the first time informed of the presence of a
+device. Only basic initialization.
+
+- Find all hardware needed for IRQ, Console, Timer and hardware
+  that need to be reset.
+- Reset hardware, so that interrupts are not generated by mistake
+  when enabled later on.
+- Init low level non-interrupt (polling-mode) services needed by
+  drivers init LEVEL2 and onwards, such as
+   * Debug UART console for printk()
+   * Timer API (non-IRQ)
+   * GPIO (non-IRQ)
+   * Special non-main memory configuration, washing
+- Register IRQ controller at BSP IRQ library
+- Register Timer for system clock
+- Register Console UART
+
+During this intialization level interrupts may not be registered, 
+enabled or disabled at the IRQ controller. But, all IRQ sources
+should be cleared to avoid spurious interrupts later on.
+
+
+AFTER LEVEL1 - if initialized during startup
+--------------------------------------------
+The statically configured drivers are initialized as normally by RTEMS. The
+hardware was found in LEVEL1.
+
+CONFIGURE_BSP_PREREQUISITE_DRIVERS may initialize IRQ driver, or 
+IRQ lib initialized when IRQ controller was registered during LEVEL1.
+
+
+LEVEL2
+------
+Initialize other device drivers than IRQ, Timer, console:
+- ISR can be registered, enabled, disabled at IRQ controller
+   (IRQ is still masked by CPU interrupt level if initialized during
+   RTEMS startup)
+- Timer API that does not require IRQ can be used
+- printf() can be used
+
+For standard peripherals this is the first initialization.
+
+
+LEVEL3
+------
+Initialize drivers that require features/APIs provided by drivers
+in LEVEL2.
+
+Such features may involve services that require IRQ to be implemented.
+
+
+LEVEL4
+------
+Unused extra level.
+
+
+
+LEVEL INACTIVE - NOT ENABLED DEVICES
+------------------------------------
+List of devices that experienced:
+ - no driver found for device (not united)
+ - ignored (not united with a driver, forced by user)
+ - an error was reported by device driver during initialization
diff --git a/cpukit/libdrvmgr/drvmgr.c b/cpukit/libdrvmgr/drvmgr.c
new file mode 100644
index 0000000..0471865
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr.c
@@ -0,0 +1,643 @@
+/* Driver Manager Interface Implementation.
+ *
+ * COPYRIGHT (c) 2009.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <drvmgr/drvmgr.h>
+#include <drvmgr/drvmgr_confdefs.h>
+
+#include "drvmgr_internal.h"
+
+/* Enable debugging */
+/*#define DEBUG 1*/
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+struct rtems_driver_manager drv_mgr = {
+	.level =		0,
+	.initializing_objs =	0,
+	.lock =                 0,
+	.root_dev =		{0},
+	.root_drv =		NULL,
+
+	.drivers =	LIST_INITIALIZER(struct drvmgr_drv, next),
+
+	.buses = {
+		LIST_INITIALIZER(struct drvmgr_bus, next),
+		LIST_INITIALIZER(struct drvmgr_bus, next),
+		LIST_INITIALIZER(struct drvmgr_bus, next),
+		LIST_INITIALIZER(struct drvmgr_bus, next),
+		LIST_INITIALIZER(struct drvmgr_bus, next),
+	},
+	.buses_inactive =	LIST_INITIALIZER(struct drvmgr_bus, next),
+
+	.devices = {
+		LIST_INITIALIZER(struct drvmgr_dev, next),
+		LIST_INITIALIZER(struct drvmgr_dev, next),
+		LIST_INITIALIZER(struct drvmgr_dev, next),
+		LIST_INITIALIZER(struct drvmgr_dev, next),
+		LIST_INITIALIZER(struct drvmgr_dev, next),
+	},
+	.devices_inactive =	LIST_INITIALIZER(struct drvmgr_dev, next),
+};
+
+static int do_bus_init(
+	struct rtems_driver_manager *mgr,
+	struct drvmgr_bus *bus,
+	int level);
+static int do_dev_init(
+	struct rtems_driver_manager *mgr,
+	struct drvmgr_dev *dev,
+	int level);
+
+/* DRIVER MANAGER */
+
+void _DRV_Manager_init_level(int level)
+{
+	struct rtems_driver_manager *mgr = &drv_mgr;
+
+	if (mgr->level >= level)
+		return;
+
+	/* Set new Level */
+	mgr->level = level;
+
+	/* Initialize buses and devices into this new level */
+	drvmgr_init_update();
+}
+
+/* Initialize Data structures of the driver manager and call driver
+ * register functions configured by the user.
+ */
+void _DRV_Manager_initialization(void)
+{
+	struct drvmgr_drv_reg_func *drvreg;
+
+	/* drv_mgr is already initialized statically by compiler except
+	 * the lock
+	 */
+	DRVMGR_LOCK_INIT();
+
+	/* Call driver register functions. */
+	drvreg = &drvmgr_drivers[0];
+	while (drvreg->drv_reg) {
+		/* Make driver register */
+		drvreg->drv_reg();
+		drvreg++;
+	}
+}
+
+/* Take ready devices and buses into the correct init level step by step.
+ * Once a bus or a device has been registered there is no turning
+ * back - they are taken to the level of the driver manager.
+ */
+void drvmgr_init_update(void)
+{
+	struct rtems_driver_manager *mgr = &drv_mgr;
+	struct drvmgr_bus *bus;
+	struct drvmgr_dev *dev;
+	int bus_might_been_registered;
+	int level;
+
+	/* "Lock" to make sure we don't use up the stack and that the lists
+	 * remain consistent.
+	 */
+	DRVMGR_LOCK_WRITE();
+	if (mgr->initializing_objs || (mgr->level == 0))
+		goto out;
+	mgr->initializing_objs = 1;
+
+init_registered_buses:
+	/* Take all buses and devices ready into the same stage
+	 * as the driver manager global level.
+	 */
+	for (level = 0; level < mgr->level; level++) {
+
+		bus_might_been_registered = 0;
+
+		/* Take buses into next level */
+
+		while ((bus = BUS_LIST_HEAD(&mgr->buses[level])) != NULL) {
+
+			/* Remove first in the list (will be inserted in
+			 * appropriate list by do_bus_init())
+			 */
+			drvmgr_list_remove_head(&mgr->buses[level]);
+
+			DRVMGR_UNLOCK();
+
+			/* Initialize Bus, this will register devices on
+			 * the bus. Take bus into next level.
+			 */
+			do_bus_init(mgr, bus, level+1);
+
+			DRVMGR_LOCK_WRITE();
+		}
+
+		/* Take devices into next level */
+		while ((dev = DEV_LIST_HEAD(&mgr->devices[level])) != NULL) {
+
+			/* Always process first in list */
+			dev = DEV_LIST_HEAD(&mgr->devices[level]);
+
+			/* Remove first in the list (will be inserted in
+			 * appropriate list by do_dev_init())
+			 */
+			drvmgr_list_remove_head(&mgr->devices[level]);
+
+			DRVMGR_UNLOCK();
+
+			/* Initialize Device, this may register a new bus */
+			do_dev_init(mgr, dev, level+1);
+
+			DRVMGR_LOCK_WRITE();
+
+			bus_might_been_registered = 1;
+		}
+
+		/* Make sure all buses registered and ready are taken at
+		 * the same time into init level N.
+		 */
+		if (bus_might_been_registered)
+			goto init_registered_buses;
+	}
+
+	/* Release bus/device initialization "Lock" */
+	mgr->initializing_objs = 0;
+
+out:
+	DRVMGR_UNLOCK();
+}
+
+/* Take bus into next level */
+static int do_bus_init(
+	struct rtems_driver_manager *mgr,
+	struct drvmgr_bus *bus,
+	int level)
+{
+	int (*init)(struct drvmgr_bus *);
+
+	/* If bridge device has failed during initialization, the bus is not
+	 * initialized further.
+	 */
+	if (bus->dev->state & DEV_STATE_INIT_FAILED) {
+		bus->state |= BUS_STATE_DEPEND_FAILED;
+		goto inactivate_out;
+	}
+
+	if (bus->ops && (init = bus->ops->init[level-1])) {
+		/* Note: This init1 function may register new devices */
+		bus->error = init(bus);
+		if (bus->error != DRVMGR_OK) {
+			/* An error of some kind during bus initialization.
+			 *
+			 * Child devices and their buses are not inactived
+			 * directly here, instead they will all be catched by
+			 * do_dev_init() and do_bus_init() by checking if
+			 * parent or bridge-device failed. We know that
+			 * initialization will happen later for those devices.
+			 */
+			goto inactivate_out;
+		}
+	}
+
+	DRVMGR_LOCK_WRITE();
+
+	/* Bus taken into the new level */
+	bus->level = level;
+
+	/* Put bus into list of buses reached level 'level'.
+	 * Put at end of bus list so that init[N+1]() calls comes
+	 * in the same order as init[N]()
+	 */
+	drvmgr_list_add_tail(&mgr->buses[level], bus);
+
+	DRVMGR_UNLOCK();
+
+	return 0;
+
+inactivate_out:
+	DRVMGR_LOCK_WRITE();
+	bus->state |= BUS_STATE_INIT_FAILED;
+	bus->state |= BUS_STATE_LIST_INACTIVE;
+	drvmgr_list_add_head(&mgr->buses_inactive, bus);
+	DRVMGR_UNLOCK();
+
+	DBG("do_bus_init(%d): (DEV: %s) failed\n", level, bus->dev->name);
+
+	return 1;
+}
+
+/* Take device to initialization level 1 */
+static int do_dev_init(
+	struct rtems_driver_manager *mgr,
+	struct drvmgr_dev *dev,
+	int level)
+{
+	int (*init)(struct drvmgr_dev *);
+
+	/* Try to allocate Private Device Structure for driver if driver
+	 * requests for this feature.
+	 */
+	if (dev->drv && dev->drv->dev_priv_size && !dev->priv) {
+		dev->priv = malloc(dev->drv->dev_priv_size);
+		memset(dev->priv, 0, dev->drv->dev_priv_size);
+	}
+
+	/* If parent bus has failed during initialization,
+	 * the device is not initialized further.
+	 */
+	if (dev->parent && (dev->parent->state & BUS_STATE_INIT_FAILED)) {
+		dev->state |= DEV_STATE_DEPEND_FAILED;
+		goto inactivate_out;
+	}
+
+	/* Call Driver's Init Routine */
+	if (dev->drv && (init = dev->drv->ops->init[level-1])) {
+		/* Note: This init function may register new devices */
+		dev->error = init(dev);
+		if (dev->error != DRVMGR_OK) {
+			/* An error of some kind has occured in the
+			 * driver/device, the failed device is put into the
+			 * inactive list, this way Init2,3 and/or 4 will not
+			 * be called for this device.
+			 *
+			 * The device is not removed from the bus (not
+			 * unregistered). The driver can be used to find
+			 * device information and debugging for example even
+			 * if device initialization failed.
+			 *
+			 * Child buses and their devices are not inactived
+			 * directly here, instead they will all be catched by
+			 * do_dev_init() and do_bus_init() by checking if
+			 * parent or bridge-device failed. We know that
+			 * initialization will happen later for those devices.
+			 */
+			goto inactivate_out;
+		}
+	}
+
+	DRVMGR_LOCK_WRITE();
+	/* Dev taken into new level */
+	dev->level = level;
+
+	/* Put at end of device list so that init[N+1]() calls comes
+	 * in the same order as init[N]()
+	 */
+	drvmgr_list_add_tail(&mgr->devices[level], dev);
+	DRVMGR_UNLOCK();
+
+	return 0;
+
+inactivate_out:
+	DRVMGR_LOCK_WRITE();
+	dev->state |= DEV_STATE_INIT_FAILED;
+	dev->state |= DEV_STATE_LIST_INACTIVE;
+	drvmgr_list_add_head(&mgr->devices_inactive, dev);
+	DRVMGR_UNLOCK();
+
+	DBG("do_dev_init(%d): DRV: %s (DEV: %s) failed\n",
+		level, dev->drv->name, dev->name);
+
+	return 1; /* Failed to take device into requested level */
+}
+
+/* Register Root device driver */
+int drvmgr_root_drv_register(struct drvmgr_drv *drv)
+{
+	struct rtems_driver_manager *mgr = &drv_mgr;
+	struct drvmgr_dev *root = &mgr->root_dev;
+
+	if (mgr->root_drv) {
+		/* Only possible to register root device once */
+		return DRVMGR_FAIL;
+	}
+
+	/* Set root device driver */
+	drv->next = NULL;
+	mgr->root_drv = drv;
+
+	/* Init root device non-NULL fields */
+	root->minor_drv = -1;
+	root->minor_bus = 0;
+	root->businfo = mgr;
+	root->name = "root bus";
+	/* Custom Driver association */
+	root->drv = mgr->root_drv;
+
+	/* This registers the root device and a bus */
+	drvmgr_dev_register(root);
+
+	return DRVMGR_OK;
+}
+
+/* Register a driver */
+int drvmgr_drv_register(struct drvmgr_drv *drv)
+{
+	struct rtems_driver_manager *mgr = &drv_mgr;
+
+	/* All drivers must have been registered before start of init, 
+	 * because the manager does not scan all existing devices to find
+	 * suitable hardware for this driver, and it is not protected with
+	 * a lock therefore.
+	 */
+	if (mgr->level > 0)
+		return -1;
+
+	drv->obj_type = DRVMGR_OBJ_DRV;
+
+	/* Put driver into list of registered drivers */
+	drvmgr_list_add_head(&mgr->drivers, drv);
+
+	/* TODO: we could scan for devices that this new driver has support
+	 *       for. However, at this stage we assume that all drivers are
+	 *       registered before devices are registered.
+	 *
+	 * LOCK: From the same assumsion locking the driver list is not needed
+	 *       either.
+	 */
+
+	return 0;
+}
+
+/* Insert a device into a driver's device list and assign a driver minor number
+ * to the device.
+ *
+ * The devices are ordered by their minor number (sorted linked list of devices)
+ * the minor number is found by looking for a gap or at the end.
+ */
+static void drvmgr_insert_dev_into_drv(
+	struct drvmgr_drv *drv,
+	struct drvmgr_dev *dev)
+{
+	struct drvmgr_dev *curr, **pprevnext;
+	int minor;
+
+	minor = 0;
+	pprevnext = &drv->dev;
+	curr = drv->dev;
+
+	while (curr) {
+		if (minor < curr->minor_drv) {
+			/* Found a gap. Insert new device between prev
+			 * and curr. */
+			break;
+		}
+		minor++;
+		pprevnext = &curr->next_in_drv;
+		curr = curr->next_in_drv;
+	}
+	dev->next_in_drv = curr;
+	*pprevnext = dev;
+
+	/* Set minor */
+	dev->minor_drv = minor;
+	drv->dev_cnt++;
+}
+
+/* Insert a device into a bus device list and assign a bus minor number to the
+ * device.
+ *
+ * The devices are ordered by their minor number (sorted linked list of devices)
+ * and by their registeration order if not using the same driver.
+ *
+ * The minor number is found by looking for a gap or at the end.
+ */
+static void drvmgr_insert_dev_into_bus(
+	struct drvmgr_bus *bus,
+	struct drvmgr_dev *dev)
+{
+	struct drvmgr_dev *curr, **pprevnext;
+	int minor;
+
+	minor = 0;
+	pprevnext = &bus->children;
+	curr = bus->children;
+
+	while (curr) {
+		if (dev->drv && (dev->drv == curr->drv)) {
+			if (minor < curr->minor_bus) {
+				/* Found a gap. Insert new device between prev
+				 * and curr. */
+				break;
+			}
+			minor++;
+		}
+		pprevnext = &curr->next_in_bus;
+		curr = curr->next_in_bus;
+	}
+	dev->next_in_bus = curr;
+	*pprevnext = dev;
+
+	/* Set minor. Devices without driver are given -1 */
+	if (dev->drv == NULL)
+		minor = -1;
+	dev->minor_bus = minor;
+	bus->dev_cnt++;
+}
+
+/* Try to find a driver for a device (unite a device with driver).
+ * a device with a driver
+ */
+static struct drvmgr_drv *drvmgr_dev_find_drv(
+		struct drvmgr_dev *dev)
+{
+	struct rtems_driver_manager *mgr = &drv_mgr;
+	struct drvmgr_drv *drv;
+
+	/* NOTE: No locking is needed here since Driver list is supposed to be
+	 *       initialized once during startup, we treat it as a static
+	 *       read-only list
+	 */
+
+	/* Try to find a driver that can handle this device */
+	for (drv = DRV_LIST_HEAD(&mgr->drivers); drv; drv = drv->next)
+		if (dev->parent->ops->unite(drv, dev) == 1)
+			break;
+
+	return drv;
+}
+
+/* Register a device */
+int drvmgr_dev_register(struct drvmgr_dev *dev)
+{
+	struct rtems_driver_manager *mgr = &drv_mgr;
+	struct drvmgr_drv *drv;
+	struct drvmgr_bus *bus = dev->parent;
+	struct drvmgr_key *keys;
+	struct drvmgr_list *init_list = &mgr->devices_inactive;
+
+	DBG("DEV_REG: %s at bus \"%s\"\n", dev->name,
+		bus && bus->dev && bus->dev->name ? bus->dev->name : "UNKNOWN");
+
+	/* Custom driver assocation? */
+	if (dev->drv) {
+		drv = dev->drv;
+		DBG("CUSTOM ASSOCIATION (%s to %s)\n", dev->name, drv->name);
+	} else {
+		/* Try to find a driver that can handle this device */
+		dev->drv = drv = drvmgr_dev_find_drv(dev);
+	}
+
+	DRVMGR_LOCK_WRITE();
+
+	/* Assign Bus Minor number and put into bus device list
+	 * unless root device.
+	 */
+	if (bus)
+		drvmgr_insert_dev_into_bus(bus, dev);
+
+	if (!drv) {
+		/* No driver found that can handle this device, put into
+		 * inactive list
+		 */
+		dev->minor_drv = -1;
+		dev->state |= DEV_STATE_LIST_INACTIVE;
+	} else {
+		/* United device with driver.
+		 * Put the device on the registered device list
+		 */
+		dev->state |= DEV_STATE_UNITED;
+
+		/* Check if user want to skip this core. This is not a
+		 * normal request, however in a multi-processor system
+		 * the two(or more) RTEMS instances must not use the same
+		 * devices in a system, not reporting a device to
+		 * it's driver will effectively accomplish this. In a
+		 * non Plug & Play system one can easily avoid this
+		 * problem by not report the core, but in a Plug & Play
+		 * system the bus driver will report all found cores.
+		 *
+		 * To stop the two RTEMS instances from using the same
+		 * device the user can simply define a resource entry
+		 * for a certain device but set the keys field to NULL.
+		 */
+		if (drvmgr_keys_get(dev, &keys) == 0 && keys == NULL) {
+			/* Found Driver resource entry point
+			 * for this device, it was NULL, this
+			 * indicates to skip the core.
+			 *
+			 * We put it into the inactive list
+			 * marking it as ignored.
+			 */
+			dev->state |= DEV_STATE_IGNORED;
+		} else {
+			/* Assign Driver Minor number and put into driver's
+			 * device list
+			 */
+			drvmgr_insert_dev_into_drv(drv, dev);
+
+			/* Just register device, it will be initialized
+			 * later together with bus.
+			 *
+			 * At the end of the list (breadth first search)
+			 */
+			init_list = &mgr->devices[0];
+
+			DBG("Registered %s (DRV: %s) on %s\n",
+				dev->name, drv->name,
+				bus ? bus->dev->name : "NO PARENT");
+		}
+	}
+
+	drvmgr_list_add_tail(init_list, dev);
+
+	DRVMGR_UNLOCK();
+
+	/* Trigger Device initialization if not root device and
+	 * has a driver
+	 */
+	if (bus && dev->drv)
+		drvmgr_init_update();
+
+	return 0;
+}
+
+/* Register a bus */
+int drvmgr_bus_register(struct drvmgr_bus *bus)
+{
+	struct rtems_driver_manager *mgr = &drv_mgr;
+	struct drvmgr_bus *bus_up;
+
+	/* Get bus architecture depth - the distance from root bus */
+	bus->depth = 0;
+	bus_up = bus->dev->parent;
+	while (bus_up) {
+		bus->depth++;
+		bus_up = bus_up->dev->parent;
+	}
+
+	DRVMGR_LOCK_WRITE();
+
+	/* Put driver into list of found buses */
+	drvmgr_list_add_tail(&mgr->buses[0], bus);
+
+	DRVMGR_UNLOCK();
+
+	/* Take bus into level1 and so on */
+	drvmgr_init_update();
+
+	return 0;
+}
+
+/* Allocate memory for a Device structure */
+int drvmgr_alloc_dev(struct drvmgr_dev **pdev, int extra)
+{
+	struct drvmgr_dev *dev;
+	int size;
+
+	size = ((sizeof(struct drvmgr_dev) + 3) & ~0x3) + extra;
+	dev = (struct drvmgr_dev *)calloc(size, 1);
+	if (!dev) {
+		/* Failed to allocate device structure - critical error */
+		rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
+	}
+	*pdev = dev;
+	dev->obj_type = DRVMGR_OBJ_DEV;
+
+	return 0;
+}
+
+/* Allocate memory for a Bus structure */
+int drvmgr_alloc_bus(struct drvmgr_bus **pbus, int extra)
+{
+	struct drvmgr_bus *bus;
+	int size;
+
+	size = ((sizeof(struct drvmgr_bus) + 3) & ~0x3) + extra;
+	bus = (struct drvmgr_bus *)calloc(size, 1);
+	if (!bus) {
+		/* Failed to allocate device structure - critical error */
+		rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
+	}
+	*pbus = bus;
+	bus->obj_type = DRVMGR_OBJ_BUS;
+
+	return 0;
+}
+
+/* Add driver resources to a bus instance */
+void drvmgr_bus_res_add(struct drvmgr_bus *bus,
+				struct drvmgr_bus_res *bres)
+{
+	/* insert first in bus resource list. Locking isn't needed since
+	 * resources can only be added before resource requests are made.
+	 * When bus has been registered resources are considered a read-only
+	 * tree.
+	 */
+	bres->next = bus->reslist;
+	bus->reslist = bres;
+}
diff --git a/cpukit/libdrvmgr/drvmgr.h b/cpukit/libdrvmgr/drvmgr.h
new file mode 100644
index 0000000..f091728
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr.h
@@ -0,0 +1,965 @@
+/* Driver Manager Interface.
+ *
+ * COPYRIGHT (c) 2009.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef _DRIVER_MANAGER_H_
+#define _DRIVER_MANAGER_H_
+
+#include <rtems.h>
+#include <drvmgr/drvmgr_list.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*** Configure Driver manager ***/
+
+/* Define the number of initialization levels of device drivers */
+#define DRVMGR_LEVEL_MAX 4
+
+/* Default to use semahpores for protection. Initialization works without
+ * locks and after initialization too if devices are not removed.
+ */
+#ifndef DRVMGR_USE_LOCKS
+#define DRVMGR_USE_LOCKS 1
+#endif
+
+struct drvmgr_dev;	/* Device */
+struct drvmgr_bus;	/* Bus */
+struct drvmgr_drv;	/* Driver */
+
+/*** List Interface shortcuts ***/
+#define BUS_LIST_HEAD(list) LIST_HEAD(list, struct drvmgr_bus)
+#define BUS_LIST_TAIL(list) LIST_TAIL(list, struct drvmgr_bus)
+#define DEV_LIST_HEAD(list) LIST_HEAD(list, struct drvmgr_dev)
+#define DEV_LIST_TAIL(list) LIST_TAIL(list, struct drvmgr_dev)
+#define DRV_LIST_HEAD(list) LIST_HEAD(list, struct drvmgr_drv)
+#define DRV_LIST_TAIL(list) LIST_TAIL(list, struct drvmgr_drv)
+
+/*** Bus indentification ***/
+#define DRVMGR_BUS_TYPE_NONE 0		/* Not a valid bus */
+#define DRVMGR_BUS_TYPE_ROOT 1		/* Hard coded bus */
+#define DRVMGR_BUS_TYPE_PCI 2		/* PCI bus */
+#define DRVMGR_BUS_TYPE_AMBAPP 3	/* AMBA Plug & Play bus */
+#define DRVMGR_BUS_TYPE_LEON2_AMBA 4	/* LEON2 hardcoded bus */
+#define DRVMGR_BUS_TYPE_AMBAPP_DIST 5	/* Distibuted AMBA Plug & Play bus accessed using a communication interface */
+#define DRVMGR_BUS_TYPE_SPW_RMAP 6	/* SpaceWire Network bus */
+#define DRVMGR_BUS_TYPE_AMBAPP_RMAP 7	/* SpaceWire RMAP accessed AMBA Plug & Play bus */
+
+enum {
+	DRVMGR_OBJ_NONE = 0,
+	DRVMGR_OBJ_DRV = 1,
+	DRVMGR_OBJ_BUS = 2,
+	DRVMGR_OBJ_DEV = 3,
+};
+
+/*** Driver indentification ***
+ *
+ * 64-bit identification integer definition
+ *  * Bus ID 8-bit [7..0]
+ *  * Reserved 8-bit field [63..56]
+ *  * Device ID specific for bus type 48-bit [55..8]  (Different buses have
+ *    different unique identifications for hardware/driver.)
+ *
+ * ID Rules
+ *  * A root bus driver must always have device ID set to 0. There can only by
+ *    one root bus driver for a certain bus type.
+ *  * A Driver ID must identify a unique hardware core
+ *
+ */
+
+/* Bus ID Mask */
+#define DRIVER_ID_BUS_MASK 0x00000000000000FFULL
+
+/* Reserved Mask for future use */
+#define DRIVER_ID_RSV_MASK 0xFF00000000000000ULL
+
+/* Reserved Mask for future use */
+#define DRIVER_ID_DEV_MASK 0x00FFFFFFFFFFFF00ULL
+
+/* Set Bus ID Mask. */
+#define DRIVER_ID(busid, devid) ((unsigned long long) \
+	((((unsigned long long)(devid) << 8) & DRIVER_ID_DEV_MASK) | \
+	 ((unsigned long long)(busid) & DRIVER_ID_BUS_MASK)))
+
+/* Get IDs */
+#define DRIVER_BUSID_GET(id)	((unsigned long long)(id) & DRIVER_ID_BUS_MASK)
+#define DRIVER_DEVID_GET(id)	(((unsigned long long)(id) & DRIVER_ID_DEV_MASK) >> 8)
+
+#define DRIVER_ROOTBUS_ID(bus_type)	DRIVER_ID(bus_type, 0)
+
+/*** Root Bus drivers ***/
+
+/* Generic Hard coded Root bus: Driver ID */
+#define DRIVER_ROOT_ID		DRIVER_ROOTBUS_ID(DRVMGR_BUS_TYPE_ROOT)
+
+/* PCI Plug & Play bus: Driver ID */
+#define DRIVER_PCIBUS_ID	DRIVER_ROOTBUS_ID(DRVMGR_BUS_TYPE_PCI)
+
+/* AMBA Plug & Play bus: Driver ID */
+#define DRIVER_GRLIB_AMBAPP_ID	DRIVER_ROOTBUS_ID(DRVMGR_BUS_TYPE_AMBAPP)
+
+/* AMBA Hard coded bus: Driver ID */
+#define DRIVER_LEON2_AMBA_ID	DRIVER_ROOTBUS_ID(DRVMGR_BUS_TYPE_LEON2_AMBA)
+
+/* Distributed AMBA Plug & Play bus: Driver ID */
+#define DRIVER_AMBAPP_DIST_ID	DRIVER_ROOTBUS_ID(DRVMGR_BUS_TYPE_AMBAPP_DIST)
+
+/*! Bus parameters used by driver interface functions to aquire information
+ * about bus. All Bus drivers should implement the operation 'get_params' so
+ * that the driver interface routines can access bus dependent information in
+ * an non-dependent way.
+ */
+struct drvmgr_bus_params {
+	char		*dev_prefix;		/*!< Optional name prefix */
+};
+
+/* Interrupt Service Routine (ISR) */
+typedef void (*drvmgr_isr)(void *arg);
+
+/*! Bus operations */
+struct drvmgr_bus_ops {
+	/* Functions used internally within driver manager */
+	int	(*init[DRVMGR_LEVEL_MAX])(struct drvmgr_bus *);
+	int	(*remove)(struct drvmgr_bus *);
+	int	(*unite)(struct drvmgr_drv *, struct drvmgr_dev *);	/*!< Unite Hardware Device with Driver */
+
+	/* Functions called indirectly from drivers */
+	int	(*int_register)(struct drvmgr_dev *, int index, const char *info, drvmgr_isr isr, void *arg);
+	int	(*int_unregister)(struct drvmgr_dev *, int index, drvmgr_isr isr, void *arg);
+	int	(*int_clear)(struct drvmgr_dev *, int index);
+	int	(*int_mask)(struct drvmgr_dev *, int index);
+	int	(*int_unmask)(struct drvmgr_dev *, int index);
+
+	/* Get Parameters */
+	int	(*get_params)(struct drvmgr_dev *, struct drvmgr_bus_params *);
+	/* Get Frequency of Bus */
+	int	(*freq_get)(struct drvmgr_dev*, int, unsigned int*);
+	/*! Function called to request information about a device. The bus
+	 *  driver interpret the bus-specific information about the device.
+	 */
+	void	(*info_dev)(struct drvmgr_dev *, void (*print)(void *p, char *str), void *p);
+};
+#define BUS_OPS_NUM (sizeof(struct drvmgr_bus_ops)/sizeof(void (*)(void)))
+
+struct drvmgr_func {
+	int funcid;
+	void *func;
+};
+#define DRVMGR_FUNC(_ID_, _FUNC_) {(int)(_ID_), (void *)(_FUNC_)}
+#define DRVMGR_FUNC_END {0, NULL}
+
+/*** Resource definitions ***
+ *
+ * Overview of structures:
+ *  All bus resources entries (_bus_res) are linked together per bus
+ *  (bus_info->reslist). One bus resource entry has a pointer to an array of
+ *  driver resources (_drv_res). One driver resouces is made out of an array
+ *  of keys (drvmgr_key). All keys belongs to the same driver and harwdare
+ *  device. Each key has a Name, Type ID and Data interpreted differently
+ *  depending on the Type ID (union drvmgr_key_value).
+ *
+ */
+
+/* Key Data Types */
+#define KEY_TYPE_NONE		0
+#define KEY_TYPE_INT		1
+#define KEY_TYPE_STRING		2
+#define KEY_TYPE_POINTER	3
+
+#define KEY_EMPTY	{NULL, KEY_TYPE_NONE, {0}}
+#define RES_EMPTY	{0, 0, NULL}
+#define MMAP_EMPTY	{0, 0, 0}
+
+/*! Union of different values */
+union drvmgr_key_value {
+	unsigned int		i;	/*!< Key data type UNSIGNED INTEGER */
+	char			*str;	/*!< Key data type STRING */
+	void			*ptr;	/*!< Key data type ADDRESS/POINTER */
+};
+
+/* One key. One Value. Holding information relevant to the driver. */
+struct drvmgr_key {
+	char			*key_name;	/* Name of key */
+	int			key_type;	/* How to interpret key_value */
+	union drvmgr_key_value	key_value;	/* The value or pointer to value */
+};
+
+/*! Driver resource entry, Driver resources for a certain device instance,
+ *  containing a number of keys where each key hold the data of interest.
+ */
+struct drvmgr_drv_res {
+	uint64_t		drv_id;		/*!< Identifies the driver this resource is aiming */
+	int			minor_bus;	/*!< Indentifies a specfic device */
+	struct drvmgr_key	*keys;		/*!< First key in key array, ended with KEY_EMPTY */
+};
+
+/*! Bus resource list node */
+struct drvmgr_bus_res {
+	struct drvmgr_bus_res	*next;		/*!< Next resource node in list */
+	struct drvmgr_drv_res	resource[];	/*!< Array of resources, one per device instance */
+};
+
+/*! MAP entry. Describes an linear address space translation. Untranslated
+ *  Start, Translated Start and length.
+ *
+ * Used by bus drivers to describe the address translation needed for
+ * the translation driver interface.
+ */
+struct drvmgr_map_entry {
+	char		*name;		/*!< Map Name */
+	unsigned int	size;		/*!< Size of map window */
+	char		*from_adr;	/*!< Start address of access window used
+					 *   to reach into remote bus */
+	char		*to_adr;	/*!< Start address of remote system
+					 *   address range */
+};
+#define DRVMGR_TRANSLATE_ONE2ONE	NULL
+#define DRVMGR_TRANSLATE_NO_BRIDGE	((void *)1)  /* No bridge, error */
+
+/*! Bus information. Describes a bus. */
+struct drvmgr_bus {
+	int			obj_type;	/*!< DRVMGR_OBJ_BUS */
+	unsigned char		bus_type;	/*!< Type of bus */
+	unsigned char		depth;		/*!< Bus level distance from root bus */
+	struct drvmgr_bus	*next;		/*!< Next Bus */
+	struct drvmgr_dev	*dev;		/*!< Bus device, the hardware... */
+	void			*priv;		/*!< Private data structure used by BUS driver */
+	struct drvmgr_dev	*children;	/*!< Hardware devices on this bus */
+	struct drvmgr_bus_ops	*ops;		/*!< Bus operations supported by this bus driver */
+	struct drvmgr_func	*funcs;		/*!< Extra operations */
+	int			dev_cnt;	/*!< Number of devices this bus has */
+	struct drvmgr_bus_res	*reslist;	/*!< Bus resources, head of a linked list of resources. */
+	struct drvmgr_map_entry	*maps_up;	/*!< Map Translation, array of address spaces upstreams to CPU */
+	struct drvmgr_map_entry	*maps_down;	/*!< Map Translation, array of address spaces downstreams to Hardware */
+
+	/* Bus status */
+	int			level;		/*!< Initialization Level of Bus */
+	int			state;		/*!< Init State of Bus, BUS_STATE_* */
+	int			error;		/*!< Return code from bus->ops->initN() */
+};
+
+/* States of a bus */
+#define BUS_STATE_INIT_FAILED	0x00000001	/* Initialization Failed */
+#define BUS_STATE_LIST_INACTIVE	0x00001000	/* In inactive bus list */
+#define BUS_STATE_DEPEND_FAILED	0x00000004	/* Device init failed */
+
+/* States of a device */
+#define DEV_STATE_INIT_FAILED	0x00000001	/* Initialization Failed */
+#define DEV_STATE_INIT_DONE	0x00000002	/* All init levels completed */
+#define DEV_STATE_DEPEND_FAILED	0x00000004	/* Parent Bus init failed */
+#define DEV_STATE_UNITED	0x00000100	/* Device United with Device Driver */
+#define DEV_STATE_REMOVED	0x00000200	/* Device has been removed (unregistered) */
+#define DEV_STATE_IGNORED	0x00000400	/* Device was ignored according to user's request, the device
+						 * was never reported to it's driver (as expected).
+						 */
+#define DEV_STATE_LIST_INACTIVE	0x00001000	/* In inactive device list */
+
+/*! Device information */
+struct drvmgr_dev {
+	int			obj_type;	/*!< DRVMGR_OBJ_DEV */
+	struct drvmgr_dev	*next;		/*!< Next device */
+	struct drvmgr_dev	*next_in_bus;	/*!< Next device on the same bus */
+	struct drvmgr_dev	*next_in_drv;	/*!< Next device using the same driver */
+
+	struct drvmgr_drv	*drv;		/*!< The driver owning this device */
+	struct drvmgr_bus	*parent;	/*!< Bus that this device resides on */
+	short			minor_drv;	/*!< Device number within driver */
+	short			minor_bus;	/*!< Device number on bus (for device separation) */
+	char			*name;		/*!< Name of Device Hardware */
+	void			*priv;		/*!< Pointer to driver private device structure */
+	void			*businfo;	/*!< Host bus specific information */
+	struct drvmgr_bus	*bus;		/*!< Pointer to bus, set only if this is a bridge */
+
+	/* Device Status */
+	unsigned int		state;		/*!< State of device, see DEV_STATE_* */
+	int			level;		/*!< Init Level */
+	int			error;		/*!< Error state returned by driver */
+};
+
+/*! Driver operations, function pointers. */
+struct drvmgr_drv_ops {
+	int	(*init[DRVMGR_LEVEL_MAX])(struct drvmgr_dev *);	/*! Function doing Init Stage 1 of a hardware device */
+	int	(*remove)(struct drvmgr_dev *);	/*! Function called when device instance is to be removed */
+	int	(*info)(struct drvmgr_dev *, void (*print)(void *p, char *str), void *p, int, char *argv[]);/*! Function called to request information about a device or driver */
+};
+#define DRV_OPS_NUM (sizeof(struct drvmgr_drv_ops)/sizeof(void (*)(void)))
+
+/*! Device driver description */
+struct drvmgr_drv {
+	int			obj_type;	/*!< DRVMGR_OBJ_DRV */
+	struct drvmgr_drv	*next;		/*!< Next Driver */
+	struct drvmgr_dev	*dev;		/*!< Devices using this driver */
+
+	uint64_t		drv_id;		/*!< Unique Driver ID */
+	char			*name;		/*!< Name of Driver */
+	int			bus_type;	/*!< Type of Bus this driver supports */
+	struct drvmgr_drv_ops	*ops;		/*!< Driver operations */
+	struct drvmgr_func	*funcs;		/*!< Extra Operations */
+	unsigned int		dev_cnt;	/*!< Number of devices in dev */
+	unsigned int		dev_priv_size;	/*!< If non-zero DRVMGR will allocate memory for dev->priv */
+};
+
+/*! Structure defines a function pointer called when driver manager is ready
+ *  for drivers to register themselfs. Used to select drivers available to the
+ *  driver manager.
+ */
+struct drvmgr_drv_reg_func {
+	void (*drv_reg)(void);
+};
+
+/*** DRIVER | DEVICE | BUS FUNCTIONS ***/
+
+/* Return Codes */
+enum {
+	DRVMGR_OK = 0,		/* Sucess */
+	DRVMGR_NOMEM = 1,	/* Memory allocation error */
+	DRVMGR_EIO = 2,		/* I/O error */
+	DRVMGR_EINVAL = 3,	/* Invalid parameter */
+	DRVMGR_ENOSYS = 4,
+	DRVMGR_TIMEDOUT = 5,	/* Operation timeout error */
+	DRVMGR_EBUSY = 6,
+	DRVMGR_ENORES = 7,	/* Not enough resources */
+	DRVMGR_FAIL = -1	/* Unspecified failure */
+};
+
+/*! Initialize data structures of the driver management system.
+ *  Calls predefined register driver functions so that drivers can
+ *  register themselves.
+ */
+extern void _DRV_Manager_initialization(void);
+
+/*! Take all devices into init level 'level', all devices registered later
+ *  will directly be taken into this level as well, ensuring that all
+ *  registerd devices has been taken into the level.
+ *
+ */
+extern void _DRV_Manager_init_level(int level);
+
+/*! This function must be defined by the BSP when the driver manager is enabled
+ * and initialized during BSP initialization. The function is called after a
+ * init level is reached the first time by the driver manager.
+ */
+extern void bsp_driver_level_hook(int level);
+
+/*! Init driver manager all in one go, will call _DRV_Manager_initialization(),
+ *  then _DRV_Manager_init_level([1..DRVMGR_LEVEL_MAX]).
+ *  Typically called from Init task when user wants to initilize driver
+ *  manager after startup, otherwise not used.
+ */
+extern int drvmgr_init(void);
+
+/* Take registered buses and devices into the correct init level,
+ * this function is called from _init_level() so normally
+ * we don't need to call it directly.
+ */
+extern void drvmgr_init_update(void);
+
+/*! Register Root Bus device driver */
+extern int drvmgr_root_drv_register(struct drvmgr_drv *drv);
+
+/*! Register a driver */
+extern int drvmgr_drv_register(struct drvmgr_drv *drv);
+
+/*! Register a device */
+extern int drvmgr_dev_register(struct drvmgr_dev *dev);
+
+/*! Remove a device, and all its children devices if device is a bus device. The
+ *  device driver will be requested to remove the device and once gone from bus,
+ *  device and driver list the device is put into a inactive list for debugging
+ *  (this is optional by using remove argument).
+ *
+ * Removing the Root Bus Device is not supported.
+ *
+ * \param remove If non-zero the device will be deallocated, and not put into
+ *               the inacitve list.
+ */
+extern int drvmgr_dev_unregister(struct drvmgr_dev *dev);
+
+/*! Register a bus */
+extern int drvmgr_bus_register(struct drvmgr_bus *bus);
+
+/*! Unregister a bus */
+extern int drvmgr_bus_unregister(struct drvmgr_bus *bus);
+
+/*! Unregister all child devices of a bus.
+ *
+ * This function is called from the bus driver, from a "safe" state where
+ * devices will not be added or removed on this particular bus at this time
+ */
+extern int drvmgr_children_unregister(struct drvmgr_bus *bus);
+
+/* Separate a device from the driver it has been united with */
+extern int drvmgr_dev_drv_separate(struct drvmgr_dev *dev);
+
+/*! Allocate a device structure, if no memory available
+ *  rtems_error_fatal_occurred is called.
+ * The 'extra' argment tells how many bytes extra space is to be allocated after
+ * the device structure, this is typically used for "businfo" structures. The extra
+ * space is always aligned to a 4-byte boundary.
+ */
+extern int drvmgr_alloc_dev(struct drvmgr_dev **pdev, int extra);
+
+/*! Allocate a bus structure, if no memory available rtems_error_fatal_occurred
+ * is called.
+ * The 'extra' argment tells how many bytes extra space is to be allocated after
+ * the device structure, this is typically used for "businfo" structures. The
+ * extra space is always aligned to a 4-byte boundary.
+ */
+extern int drvmgr_alloc_bus(struct drvmgr_bus **pbus, int extra);
+
+/*** DRIVER RESOURCE FUNCTIONS ***/
+
+/*! Add resources to a bus, typically used by a bus driver.
+ *
+ * \param bus   The Bus to add the resources to.
+ * \param res   An array with Driver resources, all together are called bus
+ *              resources.
+ */
+extern void drvmgr_bus_res_add(struct drvmgr_bus *bus,
+					struct drvmgr_bus_res *bres);
+
+/*! Find all the resource keys for a device among all driver resources on a
+ *  bus. Typically used by a device driver to get configuration options.
+ *
+ * \param dev   Device to find resources for
+ * \param key   Location where the pointer to the driver resource array (drvmgr_drv_res->keys) is stored.
+ */
+extern int drvmgr_keys_get(struct drvmgr_dev *dev, struct drvmgr_key **keys);
+
+/*! Return the one key that matches key name from a driver keys array. The keys
+ *  can be obtained using drvmgr_keys_get().
+ *
+ * \param keys       An array of keys ended with KEY_EMPTY to search among.
+ * \param key_name   Name of key to search for among the keys.
+ */
+extern struct drvmgr_key *drvmgr_key_get(struct drvmgr_key *keys, char *key_name);
+
+/*! Extract key value from the key in the keys array matching name and type.
+ *
+ *  This function calls drvmgr_keys_get to get the key requested (from key
+ *  name), then determines if the type is correct. A pointer to the key value
+ *  is returned.
+ *
+ *  \param keys       An array of keys ended with KEY_EMPTY to search among.
+ *  \param key_name   Name of key to search for among the keys.
+ *  \param key_type   Data Type of value. INTEGER, ADDRESS, STRING.
+ *  \return           Returns NULL if no value found matching Key Name and Key
+ *                    Type.
+ */
+extern union drvmgr_key_value *drvmgr_key_val_get(
+	struct drvmgr_key *keys,
+	char *key_name,
+	int key_type);
+
+/*! Get key value from the bus resources matching [device, key name, key type]
+ *  if no matching key is found NULL is returned.
+ *
+ * This is typically used by device drivers to find a particular device
+ * resource.
+ *
+ * \param dev         The device to search resource for.
+ * \param key_name    The key name to search for
+ * \param key_type    The key type expected.
+ * \return            Returns NULL if no value found matching Key Name and
+ *                    Key Type was found for device.
+ */
+extern union drvmgr_key_value *drvmgr_dev_key_get(
+	struct drvmgr_dev *dev,
+	char *key_name,
+	int key_type);
+
+/*** DRIVER INTERACE USED TO REQUEST INFORMATION/SERVICES FROM BUS DRIVER ***/
+
+/*! Get parent bus */
+static inline struct drvmgr_bus *drvmgr_get_parent(struct drvmgr_dev *dev)
+{
+	if (dev)
+		return dev->parent;
+	else
+		return NULL;
+}
+
+/*! Get Driver of device */
+static inline struct drvmgr_drv *drvmgr_get_drv(struct drvmgr_dev *dev)
+{
+	if (dev)
+		return dev->drv;
+	else
+		return NULL;
+}
+
+/*! Calls func() for every device found in the device tree, regardless of
+ * device state or if a driver is assigned. With the options argument the user
+ * can decide to do either a depth-first or a breadth-first search.
+ *
+ * If the function func() returns a non-zero value then for_each_dev will
+ * return imediatly with the same return value as func() returned.
+ *
+ * \param func       Function called on each device
+ * \param arg        Custom function argument
+ * \param options    Search Options, see DRVMGR_FED_*
+ *
+ */
+#define DRVMGR_FED_BF 1		/* Breadth-first search */
+#define DRVMGR_FED_DF 0		/* Depth first search */
+extern int drvmgr_for_each_dev(
+	int (*func)(struct drvmgr_dev *dev, void *arg),
+	void *arg,
+	int options);
+
+/*! Get Device pointer from Driver and Driver minor number
+ *
+ * \param drv         Driver the device is united with.
+ * \param minor       Driver minor number assigned to device.
+ * \param pdev        Location where the Device point will be stored.
+ * \return            Zero on success. -1 on failure, when device was not
+ *                    found in driver device list.
+ */
+extern int drvmgr_get_dev(
+	struct drvmgr_drv *drv,
+	int minor,
+	struct drvmgr_dev **pdev);
+
+/*! Get Bus frequency in Hertz. Frequency is stored into address of freq_hz.
+ *
+ * \param dev        The Device to get Bus frequency for.
+ * \param options    Bus-type specific options
+ * \param freq_hz    Location where Bus Frequency will be stored.
+ */
+extern int drvmgr_freq_get(
+	struct drvmgr_dev *dev,
+	int options,
+	unsigned int *freq_hz);
+
+/*! Return 0 if dev is not located on the root bus, 1 if on root bus */
+extern int drvmgr_on_rootbus(struct drvmgr_dev *dev);
+
+/*! Get device name prefix, this name can be used to register a unique name in
+ *  the bus->error filesystem or to get an idea where the device is located.
+ *
+ * \param dev         The Device to get the device Prefix for.
+ * \param dev_prefix  Location where the prefix will be stored.
+ */
+extern int drvmgr_get_dev_prefix(struct drvmgr_dev *dev, char *dev_prefix);
+
+/*! Register a shared interrupt handler. Since this service is shared among
+ *  interrupt drivers/handlers the handler[arg] must be installed before the
+ *  interrupt can be cleared or disabled. The handler is by default disabled
+ *  after registration.
+ *
+ *  \param index      Index is used to identify the IRQ number if hardware has
+ *                    multiple IRQ sources. Normally Index is set to 0 to
+ *                    indicated the first and only IRQ source.
+ *                    A negative index is interpreted as a absolute bus IRQ
+ *                    number.
+ *  \param isr        Interrupt Service Routine.
+ *  \param arg        Optional ISR argument.
+ */
+extern int drvmgr_interrupt_register(
+	struct drvmgr_dev *dev,
+	int index,
+	const char *info,
+	drvmgr_isr isr,
+	void *arg);
+
+/*! Unregister an interrupt handler. This also disables the interrupt before
+ *  unregistering the interrupt handler.
+ *  \param index      Index is used to identify the IRQ number if hardware has
+ *                    multiple IRQ sources. Normally Index is set to 0 to
+ *                    indicated the first and only IRQ source.
+ *                    A negative index is interpreted as a absolute bus IRQ
+ *                    number.
+ *  \param isr        Interrupt Service Routine, previously registered.
+ *  \param arg        Optional ISR argument, previously registered.
+ */
+extern int drvmgr_interrupt_unregister(
+	struct drvmgr_dev *dev,
+	int index,
+	drvmgr_isr isr,
+	void *arg);
+
+/*! Clear (ACK) pending interrupt
+ *
+ *  \param dev        Device to clear interrupt for.
+ *  \param index      Index is used to identify the IRQ number if hardware has multiple IRQ sources.
+ *                    Normally Index is set to 0 to indicated the first and only IRQ source.
+ *                    A negative index is interpreted as a absolute bus IRQ number.
+ *  \param isr        Interrupt Service Routine, previously registered.
+ *  \param arg        Optional ISR argument, previously registered.
+ */
+extern int drvmgr_interrupt_clear(
+	struct drvmgr_dev *dev,
+	int index);
+
+/*! Force unmasking/enableing an interrupt on the interrupt controller, this is not normally used,
+ *  if used the caller has masked/disabled the interrupt just before.
+ *
+ *  \param dev        Device to clear interrupt for.
+ *  \param index      Index is used to identify the IRQ number if hardware has multiple IRQ sources.
+ *                    Normally Index is set to 0 to indicated the first and only IRQ source.
+ *                    A negative index is interpreted as a absolute bus IRQ number.
+ *  \param isr        Interrupt Service Routine, previously registered.
+ *  \param arg        Optional ISR argument, previously registered.
+ */
+extern int drvmgr_interrupt_unmask(
+	struct drvmgr_dev *dev,
+	int index);
+
+/*! Force masking/disable an interrupt on the interrupt controller, this is not normally performed
+ *  since this will stop all other (shared) ISRs to be disabled until _unmask() is called.
+ *
+ *  \param dev        Device to mask interrupt for.
+ *  \param index      Index is used to identify the IRQ number if hardware has multiple IRQ sources.
+ *                    Normally Index is set to 0 to indicated the first and only IRQ source.
+ *                    A negative index is interpreted as a absolute bus IRQ number.
+ */
+extern int drvmgr_interrupt_mask(
+	struct drvmgr_dev *dev,
+	int index);
+
+/*! drvmgr_translate() translation options */
+enum drvmgr_tr_opts {
+	/* Translate CPU RAM Address (input) to DMA unit accessible address
+	 * (output), this is an upstreams translation in reverse order.
+	 *
+	 * Typical Usage:
+	 * It is common to translate a CPU accessible RAM address to an
+	 * address that DMA units can access over bridges.
+	 */
+	CPUMEM_TO_DMA = 0x0,
+
+	/* Translate DMA Unit Accessible address mapped to CPU RAM (input) to
+	 * CPU accessible address (output). This is an upstreams translation.
+	 *
+	 * Typical Usage (not often used):
+	 * The DMA unit descriptors contain pointers to DMA buffers located at
+	 * CPU RAM addresses that the DMA unit can access, the CPU processes
+	 * the descriptors and want to access the data but a translation back
+	 * to CPU address is required.
+	 */
+	CPUMEM_FROM_DMA = 0x1,
+
+	/* Translate DMA Memory Address (input) to CPU accessible address
+	 * (output), this is a downstreams translation in reverse order.
+	 *
+	 * Typical Usage:
+	 * A PCI network card puts packets into its memory not doing DMA over
+	 * PCI, in order for the CPU to access them the PCI address must be
+	 * translated.
+	 */
+	DMAMEM_TO_CPU = 0x2,
+
+	/* Translate CPU accessible address (input) mapped to DMA Memory Address
+	 * to DMA Unit accessible address (output). This is a downstreams
+	 * translation.
+	 */
+	DMAMEM_FROM_CPU = 0x3,
+};
+#define DRVMGR_TR_REVERSE 0x1	/* do reverse translation direction order */
+#define DRVMGR_TR_PATH 0x2	/* 0x0=down-stream 0x2=up-stream address path */
+ 
+/*! Translate an address on one bus to an address on another bus.
+ *
+ *  The device determines source or destination bus, the root bus is always
+ *  the other bus. It is assumed that the CPU is located on the root bus or
+ *  that it can access it without address translation (mapped 1:1). The CPU
+ *  is thus assumed to be located on level 0 top most in the bus hierarchy.
+ *
+ *  If no map is present in the bus driver src_address is translated 1:1
+ *  (just copied).
+ *
+ *  Addresses are typically converted up-streams from the DMA unit towards the
+ *  CPU (DMAMEM_TO_CPU) or down-streams towards DMA hardware from the CPU
+ *  (CPUMEM_TO_DMA) over one or multiple bridges depending on bus architecture.
+ *  See 'enum drvmgr_tr_opts' for other translation direction options.
+ *  For example:
+ *  Two common operations is to translate a CPU accessible RAM address to an
+ *  address that DMA units can access (dev=DMA-unit, CPUMEM_TO_DMA,
+ *  src_address=CPU-RAM-ADR) and to translate an address of a PCI resource for
+ *  example RAM mapped into a PCI BAR to an CPU accessible address
+ *  (dev=PCI-device, DMAMEM_TO_CPU, src_address=PCI-BAR-ADR).
+ *
+ *  Source address is translated and the result is put into *dst_address, if
+ *  the address is not accessible on the other bus -1 is returned.
+ *
+ *  \param dev             Device to translate addresses for
+ *  \param options         Tanslation direction options, see enum drvmgr_tr_opts
+ *  \param src_address     Address to translate
+ *  \param dst_address     Location where translated address is stored
+ *
+ *  Returns 0 if unable to translate. The remaining length from the given
+ *  address of the map is returned on success, for example if a map starts
+ *  at 0x40000000 of size 0x100000 the result will be 0x40000 if the address
+ *  was translated into 0x400C0000.
+ *  If dev is on root-bus no translation is performed 0xffffffff is returned
+ *  and src_address is stored in *dst_address.
+ */
+extern unsigned int drvmgr_translate(
+	struct drvmgr_dev *dev,
+	unsigned int options,
+	void *src_address,
+	void **dst_address);
+
+/* Translate addresses between buses, used internally to implement
+ * drvmgr_translate. Function is not limited to translate from/to root bus
+ * where CPU is resident, however buses must be on a straight path relative
+ * to each other (parent of parent of parent and so on).
+ *
+ * \param from         src_address is given for this bus
+ * \param to           src_address is translated to this bus
+ * \param reverse      Selects translation method, if map entries are used in
+ *                     the reverse order (map_up->to is used as map_up->from)
+ * \param src_address  Address to be translated
+ * \param dst_address  Translated address is stored here on success (return=0)
+ *
+ *  Returns 0 if unable to translate. The remaining length from the given
+ *  address of the map is returned on success and the result is stored into
+ *  *dst_address. For example if a map starts at 0x40000000 of size 0x100000
+ *  the result will be 0x40000 if the address was translated into 0x400C0000.
+ *  If dev is on root-bus no translation is performed 0xffffffff is returned.
+ *  and src_address is stored in *dst_address.
+ */
+extern unsigned int drvmgr_translate_bus(
+	struct drvmgr_bus *from,
+	struct drvmgr_bus *to,
+	int reverse,
+	void *src_address,
+	void **dst_address);
+
+/* Calls drvmgr_translate() to translate an address range and checks the result,
+ * a printout is generated if the check fails. All parameters are passed on to
+ * drvmgr_translate() except for size, see paramters of drvmgr_translate().
+ *
+ * If size=0 only the starting address is not checked.
+ *
+ * If mapping failes a non-zero result is returned.
+ */
+extern int drvmgr_translate_check(
+	struct drvmgr_dev *dev,
+	unsigned int options,
+	void *src_address,
+	void **dst_address,
+	unsigned int size);
+
+/*! Get function pointer from Device Driver or Bus Driver.
+ *
+ *  Returns 0 if function is available
+ */
+extern int drvmgr_func_get(void *obj, int funcid, void **func);
+
+/*! Lookup function and call it directly with the four optional arguments */
+extern int drvmgr_func_call(void *obj, int funcid, void *a, void *b, void *c, void *d);
+
+/* Builds a Function ID.
+ *
+ * Used to request optional functions by a bus or device driver
+ */
+#define DRVMGR_FUNCID(major, minor) ((((major) & 0xfff) << 20) | ((minor) & 0xfffff))
+#define DRVMGR_FUNCID_NONE 0
+#define DRVMGR_FUNCID_END DRVMGR_FUNCID(DRVMGR_FUNCID_NONE, 0)
+
+/* Major Function ID. Most significant 12-bits. */
+enum {
+	FUNCID_NONE             = 0x000,
+	FUNCID_RW               = 0x001, /* Read/Write functions */
+};
+
+/* Select Sub-Function Read/Write function by ID */
+#define RW_SIZE_1   0x00001    /* Access Size */
+#define RW_SIZE_2   0x00002
+#define RW_SIZE_4   0x00004
+#define RW_SIZE_8   0x00008
+#define RW_SIZE_ANY 0x00000
+#define RW_SIZE(id) ((unsigned int)(id) & 0xf)
+
+#define RW_DIR_ANY  0x00000   /* Access Direction */
+#define RW_READ     0x00000   /* Read */
+#define RW_WRITE    0x00010   /* Write */
+#define RW_SET      0x00020   /* Write with same value (memset) */
+#define RW_DIR(id)  (((unsigned int)(id) >> 4) & 0x3)
+
+#define RW_RAW      0x00000  /* Raw access - no swapping (machine default) */
+#define RW_LITTLE   0x00040  /* Little Endian */
+#define RW_BIG      0x00080  /* Big Endian */
+#define RW_ENDIAN(id) (((unsigned int)(id) >> 6) & 0x3)
+
+#define RW_TYPE_ANY 0x00000  /* Access type */
+#define RW_REG      0x00100
+#define RW_MEM      0x00200
+#define RW_MEMREG   0x00300
+#define RW_CFG      0x00400
+#define RW_TYPE(id) (((unsigned int)(id) >> 8) & 0xf)
+
+#define RW_ARG      0x01000 /* Optional Argument */
+#define RW_ERR      0x02000 /* Optional Error Handler */
+
+/* Build a Read/Write function ID */
+#define DRVMGR_RWFUNC(minor) DRVMGR_FUNCID(FUNCID_RW, minor)
+
+/* Argument to Read/Write functions, the "void *arg" pointer is returned by
+ * RW_ARG. If NULL is returned no argument is needed.
+ */
+struct drvmgr_rw_arg {
+	void *arg;
+	struct drvmgr_dev *dev;
+};
+
+/* Standard Read/Write function types */
+typedef uint8_t (*drvmgr_r8)(uint8_t *srcadr);
+typedef uint16_t (*drvmgr_r16)(uint16_t *srcadr);
+typedef uint32_t (*drvmgr_r32)(uint32_t *srcadr);
+typedef uint64_t (*drvmgr_r64)(uint64_t *srcadr);
+typedef void (*drvmgr_w8)(uint8_t *dstadr, uint8_t data);
+typedef void (*drvmgr_w16)(uint16_t *dstadr, uint16_t data);
+typedef void (*drvmgr_w32)(uint32_t *dstadr, uint32_t data);
+typedef void (*drvmgr_w64)(uint64_t *dstadr, uint64_t data);
+/* READ/COPY a memory area located on bus into CPU memory.
+ * From 'src' (remote) to the destination 'dest' (local), n=number of bytes
+ */
+typedef int (*drvmgr_rmem)(void *dest, const void *src, int n);
+/* WRITE/COPY a user buffer located in CPU memory to a location on the bus.
+ * From 'src' (local) to the destination 'dest' (remote), n=number of bytes
+ */
+typedef int (*drvmgr_wmem)(void *dest, const void *src, int n);
+/* Set a memory area to the byte value given in c, see LIBC memset(). Memset is
+ * implemented by calling wmem() multiple times with a "large" buffer.
+ */
+typedef int (*drvmgr_memset)(void *dstadr, int c, size_t n);
+
+/* Read/Write function types with additional argument */
+typedef uint8_t (*drvmgr_r8_arg)(uint8_t *srcadr, void *a);
+typedef uint16_t (*drvmgr_r16_arg)(uint16_t *srcadr, void *a);
+typedef uint32_t (*drvmgr_r32_arg)(uint32_t *srcadr, void *a);
+typedef uint64_t (*drvmgr_r64_arg)(uint64_t *srcadr, void *a);
+typedef void (*drvmgr_w8_arg)(uint8_t *dstadr, uint8_t data, void *a);
+typedef void (*drvmgr_w16_arg)(uint16_t *dstadr, uint16_t data, void *a);
+typedef void (*drvmgr_w32_arg)(uint32_t *dstadr, uint32_t data, void *a);
+typedef void (*drvmgr_w64_arg)(uint64_t *dstadr, uint64_t data, void *a);
+typedef int (*drvmgr_rmem_arg)(void *dest, const void *src, int n, void *a);
+typedef int (*drvmgr_wmem_arg)(void *dest, const void *src, int n, void *a);
+typedef int (*drvmgr_memset_arg)(void *dstadr, int c, size_t n, void *a);
+
+/* Report an error to the parent bus of the device */
+typedef void (*drvmgr_rw_err)(struct drvmgr_rw_arg *a, struct drvmgr_bus *bus,
+				int funcid, void *adr);
+
+/* Helper function for buses that implement the memset() over wmem() */
+extern void drvmgr_rw_memset(
+	void *dstadr,
+	int c,
+	size_t n,
+	void *a,
+	drvmgr_wmem_arg wmem
+	);
+
+/*** PRINT INFORMATION ABOUT DRIVER MANAGER ***/
+
+/*! Calls func() for every device found matching the search requirements of
+ * set_mask and clr_mask. Each bit set in set_mask must be set in the
+ * device state bit mask (dev->state), and Each bit in the clr_mask must
+ * be cleared in the device state bit mask (dev->state). There are three
+ * special cases:
+ *
+ * 1. If state_set_mask and state_clr_mask are zero the state bits are
+ *    ignored and all cores are treated as a match.
+ *
+ * 2. If state_set_mask is zero the function func will not be called due to
+ *    a bit being set in the state mask.
+ *
+ * 3. If state_clr_mask is zero the function func will not be called due to
+ *    a bit being cleared in the state mask.
+ *
+ * If the function func() returns a non-zero value then for_each_dev will
+ * return imediatly with the same return value as func() returned.
+ *
+ * \param devlist            The list to iterate though searching for devices.
+ * \param state_set_mask     Defines the bits that must be set in dev->state
+ * \param state_clr_mask     Defines the bits that must be cleared in dev->state
+ * \param func               Function called on each
+ *
+ */
+extern int drvmgr_for_each_listdev(
+	struct drvmgr_list *devlist,
+	unsigned int state_set_mask,
+	unsigned int state_clr_mask,
+	int (*func)(struct drvmgr_dev *dev, void *arg),
+	void *arg);
+
+/* Print all devices */
+#define PRINT_DEVS_FAILED	0x01	/* Failed during initialization */
+#define PRINT_DEVS_ASSIGNED	0x02	/* Driver assigned */
+#define PRINT_DEVS_UNASSIGNED	0x04	/* Driver not assigned */
+#define PRINT_DEVS_IGNORED	0x08	/* Device ignored on user's request */
+#define PRINT_DEVS_ALL		(PRINT_DEVS_FAILED | \
+				PRINT_DEVS_ASSIGNED | \
+				PRINT_DEVS_UNASSIGNED |\
+				PRINT_DEVS_IGNORED)
+
+/*! Print number of devices, buses and drivers */
+extern void drvmgr_summary(void);
+
+/*! Print devices with certain condictions met according to 'options' */
+extern void drvmgr_print_devs(unsigned int options);
+
+/*! Print device/bus topology */
+extern void drvmgr_print_topo(void);
+
+/*! Print the memory usage
+ * Only accounts for data structures. Not for the text size.
+ */
+extern void drvmgr_print_mem(void);
+
+#define OPTION_DEV_GENINFO   0x00000001
+#define OPTION_DEV_BUSINFO   0x00000002
+#define OPTION_DEV_DRVINFO   0x00000004
+#define OPTION_DRV_DEVS      0x00000100
+#define OPTION_BUS_DEVS      0x00010000
+#define OPTION_RECURSIVE     0x01000000
+#define OPTION_INFO_ALL      0xffffffff
+
+/*! Print information about a driver manager object (device, driver, bus) */
+extern void drvmgr_info(void *id, unsigned int options);
+
+/*! Get information about a device */
+extern void drvmgr_info_dev(struct drvmgr_dev *dev, unsigned int options);
+
+/*! Get information about a bus */
+extern void drvmgr_info_bus(struct drvmgr_bus *bus, unsigned int options);
+
+/*! Get information about a driver */
+extern void drvmgr_info_drv(struct drvmgr_drv *drv, unsigned int options);
+
+/*! Get information about all devices on a bus */
+extern void drvmgr_info_devs_on_bus(struct drvmgr_bus *bus, unsigned int options);
+
+/*! Get information about all devices in the system (on all buses) */
+extern void drvmgr_info_devs(unsigned int options);
+
+/*! Get information about all drivers in the system */
+extern void drvmgr_info_drvs(unsigned int options);
+
+/*! Get information about all buses in the system */
+extern void drvmgr_info_buses(unsigned int options);
+
+/*! Get Driver by Driver ID */
+extern struct drvmgr_drv *drvmgr_drv_by_id(uint64_t id);
+
+/*! Get Driver by Driver Name */
+extern struct drvmgr_drv *drvmgr_drv_by_name(const char *name);
+
+/*! Get Device by Device Name */
+extern struct drvmgr_dev *drvmgr_dev_by_name(const char *name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libdrvmgr/drvmgr_by_id.c b/cpukit/libdrvmgr/drvmgr_by_id.c
new file mode 100644
index 0000000..7a0ea42
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_by_id.c
@@ -0,0 +1,33 @@
+/* Find driver by driver-ID
+ *
+ * COPYRIGHT (c) 2011.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <drvmgr/drvmgr.h>
+#include "drvmgr_internal.h"
+
+/* Get driver from driver name */
+struct drvmgr_drv *drvmgr_drv_by_id(uint64_t id)
+{
+	struct rtems_driver_manager *mgr = &drv_mgr;
+	struct drvmgr_drv *drv = NULL;
+
+	/* NOTE: No locking is needed here since Driver list is supposed to be
+	 *       initialized once during startup, we treat it as a static
+	 *       read-only list
+	 */
+
+	drv = DRV_LIST_HEAD(&mgr->drivers);
+	while (drv) {
+		if (drv->drv_id == id)
+			break;
+		drv = drv->next;
+	}
+
+	return drv;
+}
diff --git a/cpukit/libdrvmgr/drvmgr_by_name.c b/cpukit/libdrvmgr/drvmgr_by_name.c
new file mode 100644
index 0000000..2ae527a
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_by_name.c
@@ -0,0 +1,37 @@
+/* Find driver by driver-name
+ *
+ * COPYRIGHT (c) 2011.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <string.h>
+#include <drvmgr/drvmgr.h>
+#include "drvmgr_internal.h"
+
+/* Get driver from driver name */
+struct drvmgr_drv *drvmgr_drv_by_name(const char *name)
+{
+	struct rtems_driver_manager *mgr = &drv_mgr;
+	struct drvmgr_drv *drv = NULL;
+
+	if (!name)
+		return NULL;
+
+	/* NOTE: No locking is needed here since Driver list is supposed to be
+	 *       initialized once during startup, we treat it as a static
+	 *       read-only list
+	 */
+
+	drv = DRV_LIST_HEAD(&mgr->drivers);
+	while (drv) {
+		if (drv->name && (strcmp(drv->name, name) == 0))
+			break;
+		drv = drv->next;
+	}
+
+	return drv;
+}
diff --git a/cpukit/libdrvmgr/drvmgr_confdefs.h b/cpukit/libdrvmgr/drvmgr_confdefs.h
new file mode 100644
index 0000000..23affe9
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_confdefs.h
@@ -0,0 +1,86 @@
+/* Driver Manager Configuration file.
+ *
+ * COPYRIGHT (c) 2009.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+/*
+ *  The configuration consist of an array with function pointers that
+ *  register one or more drivers that will be used by the Driver Manger.
+ *
+ *  The Functions are called in the order they are declared.
+ *
+ */
+
+#ifndef _DRIVER_MANAGER_CONFDEFS_H_
+#define _DRIVER_MANAGER_CONFDEFS_H_
+
+#include "drvmgr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct drvmgr_drv_reg_func drvmgr_drivers[];
+
+#ifdef CONFIGURE_INIT
+
+#if 0 /* EXAMPLE: GPTIMER driver definition */
+#define DRIVER_AMBAPP_GAISLER_GPTIMER_REG {gptimer_register_drv}
+extern void gptimer_register_drv(void);
+#endif
+
+/* CONFIGURE DRIVER MANAGER */
+struct drvmgr_drv_reg_func drvmgr_drivers[] = {
+#if 0 /* EXAMPLE: GPTIMER Driver registration */
+#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_GPTIMER
+	DRIVER_AMBAPP_GAISLER_GPTIMER_REG,
+#endif
+#endif
+
+/* Macros for adding custom drivers without needing to recompile
+ * kernel.
+ */
+#ifdef CONFIGURE_DRIVER_CUSTOM1
+	DRIVER_CUSTOM1_REG,
+#endif
+#ifdef CONFIGURE_DRIVER_CUSTOM2
+	DRIVER_CUSTOM2_REG,
+#endif
+#ifdef CONFIGURE_DRIVER_CUSTOM3
+	DRIVER_CUSTOM3_REG,
+#endif
+#ifdef CONFIGURE_DRIVER_CUSTOM4
+	DRIVER_CUSTOM4_REG,
+#endif
+#ifdef CONFIGURE_DRIVER_CUSTOM5
+	DRIVER_CUSTOM5_REG,
+#endif
+#ifdef CONFIGURE_DRIVER_CUSTOM6
+	DRIVER_CUSTOM6_REG,
+#endif
+#ifdef CONFIGURE_DRIVER_CUSTOM7
+	DRIVER_CUSTOM7_REG,
+#endif
+#ifdef CONFIGURE_DRIVER_CUSTOM8
+	DRIVER_CUSTOM8_REG,
+#endif
+#ifdef CONFIGURE_DRIVER_CUSTOM9
+	DRIVER_CUSTOM9_REG,
+#endif
+
+	/* End array with NULL */
+	{NULL}
+};
+
+#endif /* CONFIGURE_INIT */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DRIVER_MANAGER_CONFDEFS_H_ */
diff --git a/cpukit/libdrvmgr/drvmgr_dev_by_name.c b/cpukit/libdrvmgr/drvmgr_dev_by_name.c
new file mode 100644
index 0000000..f5a99ee
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_dev_by_name.c
@@ -0,0 +1,34 @@
+/* Find device by device name
+ *
+ * COPYRIGHT (c) 2011.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ */
+
+#include <string.h>
+#include <drvmgr/drvmgr.h>
+#include "drvmgr_internal.h"
+
+static int dev_name_compare(struct drvmgr_dev *dev, void *arg)
+{
+	const char *name = arg;
+
+	if (dev->name && (strcmp(dev->name, name) == 0))
+		return (int)dev;
+	else
+		return 0;
+}
+
+/* Get device by device name or bus name */
+struct drvmgr_dev *drvmgr_dev_by_name(const char *name)
+{
+	if (!name)
+		return NULL;
+
+	return (struct drvmgr_dev *)
+		drvmgr_for_each_dev(dev_name_compare, (void *)name, 0);
+}
diff --git a/cpukit/libdrvmgr/drvmgr_drvinf.c b/cpukit/libdrvmgr/drvmgr_drvinf.c
new file mode 100644
index 0000000..9f7c7a5
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_drvinf.c
@@ -0,0 +1,148 @@
+/* Driver Manager Driver Interface Implementation.
+ *
+ * COPYRIGHT (c) 2009.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ */
+
+/*
+ * This is the part the device driver API, the functions rely on that the
+ * parent bus driver has implemented the neccessary operations correctly.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <drvmgr/drvmgr.h>
+#include "drvmgr_internal.h"
+
+/* Get device pointer from knowing the Driver and the Driver minor
+ * that was assigned to it
+ */
+int drvmgr_get_dev(
+	struct drvmgr_drv *drv,
+	int minor,
+	struct drvmgr_dev **pdev)
+{
+	struct drvmgr_dev *dev;
+	if (!drv)
+		return -1;
+
+	DRVMGR_LOCK_READ();
+	dev = drv->dev;
+	while (dev) {
+		if (dev->minor_drv == minor)
+			break;
+		dev = dev->next_in_drv;
+	}
+	DRVMGR_UNLOCK();
+	if (!dev)
+		return -1;
+	if (pdev)
+		*pdev = dev;
+	return 0;
+}
+
+/* Get Bus frequency in HZ from bus driver */
+int drvmgr_freq_get(
+	struct drvmgr_dev *dev,
+	int options,
+	unsigned int *freq_hz)
+{
+	if (!dev || !dev->parent || !dev->parent->ops->freq_get)
+		return -1;
+
+	return dev->parent->ops->freq_get(dev, options, freq_hz);
+}
+
+/* Get driver prefix */
+int drvmgr_get_dev_prefix(struct drvmgr_dev *dev, char *dev_prefix)
+{
+	struct drvmgr_bus_params params;
+	if (!dev || !dev->parent || !dev->parent->ops->get_params)
+		return -1;
+
+	dev->parent->ops->get_params(dev, &params);
+	if (!params.dev_prefix)
+		return -1;
+	if (dev_prefix)
+		strcpy(dev_prefix, params.dev_prefix);
+	return 0;
+}
+
+/* Register an interrupt */
+int drvmgr_interrupt_register(
+	struct drvmgr_dev *dev,
+	int index,
+	const char *info,
+	drvmgr_isr isr,
+	void *arg)
+{
+	if (!dev || !dev->parent || !dev->parent->ops->int_register)
+		return -1;
+
+	if (!isr)
+		return -1;
+
+	return dev->parent->ops->int_register(dev, index, info, isr, arg);
+}
+
+/* Unregister an interrupt */
+int drvmgr_interrupt_unregister(
+	struct drvmgr_dev *dev,
+	int index,
+	drvmgr_isr isr,
+	void *arg)
+{
+	if (!dev || !dev->parent || !dev->parent->ops->int_unregister)
+		return -1;
+
+	if (!isr)
+		return -1;
+
+	return dev->parent->ops->int_unregister(dev, index, isr, arg);
+}
+
+int drvmgr_interrupt_clear(
+	struct drvmgr_dev *dev,
+	int index)
+{
+	if (!dev || !dev->parent || !dev->parent->ops->int_clear)
+		return -1;
+
+	return dev->parent->ops->int_clear(dev, index);
+}
+
+int drvmgr_interrupt_unmask(
+	struct drvmgr_dev *dev,
+	int index)
+{
+	if (!dev || !dev->parent || !dev->parent->ops->int_unmask)
+		return -1;
+
+	return dev->parent->ops->int_unmask(dev, index);
+}
+
+int drvmgr_interrupt_mask(
+	struct drvmgr_dev *dev,
+	int index)
+{
+	if (!dev || !dev->parent || !dev->parent->ops->int_mask)
+		return -1;
+
+	return dev->parent->ops->int_mask(dev, index);
+}
+
+int drvmgr_on_rootbus(struct drvmgr_dev *dev)
+{
+	if (dev->parent && dev->parent->dev && dev->parent->dev->parent)
+		return 0;
+	else
+		return 1;
+}
diff --git a/cpukit/libdrvmgr/drvmgr_for_each_dev.c b/cpukit/libdrvmgr/drvmgr_for_each_dev.c
new file mode 100644
index 0000000..a3e63ec
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_for_each_dev.c
@@ -0,0 +1,104 @@
+/* Iterate over device tree topology, breadth or depth-first
+ *
+ * COPYRIGHT (c) 2009.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <string.h>
+#include <drvmgr/drvmgr.h>
+#include <drvmgr/drvmgr_list.h>
+#include "drvmgr_internal.h"
+
+/* Traverse device tree breadth-first. Supports up to 31 buses */
+static int drvmgr_for_each_dev_breadth(
+	int (*func)(struct drvmgr_dev *dev, void *arg),
+	void *arg
+	)
+{
+	int ret = 0, i, pos;
+	struct drvmgr_bus *bus, *buses[32];
+	struct drvmgr_dev *dev;
+
+	pos = 0;
+	memset(&buses[0], 0, sizeof(buses));
+	buses[pos++] = drv_mgr.root_dev.bus; 	/* Get root bus */
+
+	for (i = 0, bus = buses[0]; buses[i]; i++, bus = buses[i]) {
+		dev = bus->children;
+		while (dev) {
+			ret = func(dev, arg);
+			if (ret != 0)
+				break;
+			if (dev->bus && pos < 31)
+				buses[pos++] = dev->bus;
+
+			dev = dev->next_in_bus;
+		}
+	}
+
+	return ret;
+}
+
+/* Traverse device tree depth-first. */
+static int drvmgr_for_each_dev_depth(
+	int (*func)(struct drvmgr_dev *dev, void *arg),
+	void *arg
+	)
+{
+	int ret = 0;
+	struct drvmgr_dev *dev;
+
+	/* Get first device */
+	dev = drv_mgr.root_dev.bus->children;
+
+	while (dev) {
+		ret = func(dev, arg);
+		if (ret != 0)
+			break;
+		if (dev->bus && dev->bus->children) {
+			dev = dev->bus->children;
+		} else {
+next_dev:
+			if (dev->next_in_bus == NULL) {
+				/* Step up one level... back to parent bus */
+				dev = dev->parent->dev;
+				if (dev == &drv_mgr.root_dev)
+					break;
+				goto next_dev;
+			} else {
+				dev = dev->next_in_bus;
+			}
+		}
+	}
+
+	return ret;
+}
+
+/* Traverse device tree depth-first or breadth-first */
+int drvmgr_for_each_dev(
+	int (*func)(struct drvmgr_dev *dev, void *arg),
+	void *arg,
+	int options
+	)
+{
+	int ret;
+
+	DRVMGR_LOCK_READ();
+
+	/* Get Root Device */
+	if (drv_mgr.root_dev.bus->children != NULL) {
+		if (options & DRVMGR_FED_BF)
+			ret = drvmgr_for_each_dev_breadth(func, arg);
+		else
+			ret = drvmgr_for_each_dev_depth(func, arg);
+	} else
+		ret = 0;
+
+	DRVMGR_UNLOCK();
+
+	return ret;
+}
diff --git a/cpukit/libdrvmgr/drvmgr_for_each_list_dev.c b/cpukit/libdrvmgr/drvmgr_for_each_list_dev.c
new file mode 100644
index 0000000..9e1b95b
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_for_each_list_dev.c
@@ -0,0 +1,44 @@
+/* Iterate over one list of devices used internally by driver manager
+ *
+ * COPYRIGHT (c) 2009.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <drvmgr/drvmgr.h>
+#include <drvmgr/drvmgr_list.h>
+#include "drvmgr_internal.h"
+
+int drvmgr_for_each_listdev(
+	struct drvmgr_list *devlist,
+	unsigned int state_set_mask,
+	unsigned int state_clr_mask,
+	int (*func)(struct drvmgr_dev *dev, void *arg),
+	void *arg
+	)
+{
+	struct drvmgr_dev *dev;
+	int ret = 0;
+
+	DRVMGR_LOCK_READ();
+
+	/* Get First Device */
+	dev = DEV_LIST_HEAD(devlist);
+	while (dev) {
+		if (((state_set_mask != 0) && ((dev->state & state_set_mask) == state_set_mask)) ||
+		    ((state_clr_mask != 0) && ((dev->state & state_clr_mask) == 0)) ||
+		    ((state_set_mask == 0) && (state_clr_mask == 0))) {
+			ret = func(dev, arg);
+			if (ret != 0)
+				break;
+		}
+		dev = dev->next;
+	}
+
+	DRVMGR_UNLOCK();
+
+	return ret;
+}
diff --git a/cpukit/libdrvmgr/drvmgr_func.c b/cpukit/libdrvmgr/drvmgr_func.c
new file mode 100644
index 0000000..e02a444
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_func.c
@@ -0,0 +1,42 @@
+/* Driver Manager optional dynamic function interface
+ *
+ * COPYRIGHT (c) 2011.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <drvmgr/drvmgr.h>
+
+/* Get Function from Function ID */
+int drvmgr_func_get(void *obj, int funcid, void **func)
+{
+	int objtype;
+	struct drvmgr_func *f;
+
+	if (!obj)
+		return DRVMGR_FAIL;
+	objtype = *(int *)obj;
+
+	if (objtype == DRVMGR_OBJ_BUS)
+		f = ((struct drvmgr_bus *)obj)->funcs;
+	else if (objtype == DRVMGR_OBJ_DRV)
+		f = ((struct drvmgr_drv *)obj)->funcs;
+	else
+		return DRVMGR_FAIL;
+
+	if (f == NULL)
+		return DRVMGR_FAIL;
+
+	while (f->funcid != DRVMGR_FUNCID_NONE) {
+		if (f->funcid == funcid) {
+			*func = f->func;
+			return DRVMGR_OK;
+		}
+		f++;
+	}
+
+	return DRVMGR_FAIL;
+}
diff --git a/cpukit/libdrvmgr/drvmgr_func_call.c b/cpukit/libdrvmgr/drvmgr_func_call.c
new file mode 100644
index 0000000..75836c3
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_func_call.c
@@ -0,0 +1,21 @@
+/* Driver Manager optional dynamic function interface
+ *
+ * COPYRIGHT (c) 2011.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <drvmgr/drvmgr.h>
+
+/* Lookup function from function ID and call it using given arguments */
+int drvmgr_func_call(void *obj, int funcid, void *a, void *b, void *c, void *d)
+{
+	int (*func)(void *arg1, void *arg2, void *arg3, void *arg4) = NULL;
+
+	if (drvmgr_func_get(obj, funcid, (void *)&func) != DRVMGR_OK)
+		return DRVMGR_FAIL;
+	return func(a, b, c, d);
+}
diff --git a/cpukit/libdrvmgr/drvmgr_init.c b/cpukit/libdrvmgr/drvmgr_init.c
new file mode 100644
index 0000000..b8a738f
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_init.c
@@ -0,0 +1,26 @@
+/* Driver Manager Initialization
+ *
+ * COPYRIGHT (c) 2009.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <drvmgr/drvmgr.h>
+
+/* Init driver manager - all in one go. Typically called from Init task when
+ * user wants to initilize driver manager after startup, otherwise not used.
+ */
+int drvmgr_init(void)
+{
+	int level;
+
+	_DRV_Manager_initialization();
+
+	for (level = 1; level <= DRVMGR_LEVEL_MAX; level++)
+		_DRV_Manager_init_level(level);
+
+	return 0;
+}
diff --git a/cpukit/libdrvmgr/drvmgr_internal.h b/cpukit/libdrvmgr/drvmgr_internal.h
new file mode 100644
index 0000000..b459455
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_internal.h
@@ -0,0 +1,70 @@
+/* Private driver manager declarations
+ *
+ * COPYRIGHT (c) 2009.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+/*  Structure hold all information the driver manager needs to know of. Used
+ *  internally by Driver Manager routines.
+ */
+struct rtems_driver_manager {
+	int	level;
+	int	initializing_objs;
+
+	/* Device tree Lock */
+	rtems_id		lock;
+
+	/* The first device - The root device and it's driver */
+	struct drvmgr_drv	*root_drv;
+	struct drvmgr_dev	root_dev;
+
+	/*!< Linked list of all registered drivers */
+	struct drvmgr_list	drivers;
+
+	/* Buses that reached a certain initialization level.
+	 * Lists by Level:
+	 *  N=0         - Not intialized, just registered
+	 *  N=1..MAX-1  - Reached init level N
+	 *  N=MAX       - Successfully initialized bus
+	 */
+	struct drvmgr_list	buses[DRVMGR_LEVEL_MAX+1];
+	/* Buses failed to initialize or has been removed by not freed */
+	struct drvmgr_list	buses_inactive;
+
+	/* Devices that reached a certain initialization level.
+	 * Lists by Level:
+	 *  N=0         - Not intialized, just registered
+	 *  N=1..MAX-1  - Reached init level N
+	 *  N=MAX       - Successfully initialized device
+	 */
+	struct drvmgr_list	devices[DRVMGR_LEVEL_MAX+1];
+	/*!< Devices failed to initialize, removed, ignored, no driver */
+	struct drvmgr_list	devices_inactive;
+};
+
+extern struct rtems_driver_manager drv_mgr;
+
+extern void _DRV_Manager_Lock(void);
+extern void _DRV_Manager_Unlock(void);
+extern int _DRV_Manager_Init_Lock(void);
+
+/* The best solution is to implement the locking with a RW lock, however there
+ * is no such API available. Care must be taken so that dead-lock isn't created
+ * for example in recursive functions.
+ */
+#if defined(DRVMGR_USE_LOCKS) && (DRVMGR_USE_LOCKS == 1)
+ #define DRVMGR_LOCK_INIT() _DRV_Manager_Init_Lock()
+ #define DRVMGR_LOCK_WRITE() _DRV_Manager_Lock()
+ #define DRVMGR_LOCK_READ() _DRV_Manager_Lock()
+ #define DRVMGR_UNLOCK() _DRV_Manager_Unlock()
+#else
+ /* no locking */
+ #define DRVMGR_LOCK_INIT() 
+ #define DRVMGR_LOCK_WRITE() 
+ #define DRVMGR_LOCK_READ() 
+ #define DRVMGR_UNLOCK() 
+#endif
diff --git a/cpukit/libdrvmgr/drvmgr_list.c b/cpukit/libdrvmgr/drvmgr_list.c
new file mode 100644
index 0000000..dc1665f
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_list.c
@@ -0,0 +1,67 @@
+/* Driver Manager List Interface Implementation.
+ *
+ * COPYRIGHT (c) 2009.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <stdlib.h>
+#include <drvmgr/drvmgr_list.h>
+
+/* LIST interface */
+
+void drvmgr_list_init(struct drvmgr_list *list, int offset)
+{
+	list->head = list->tail = NULL;
+	list->ofs = offset;
+}
+
+void drvmgr_list_empty(struct drvmgr_list *list)
+{
+	list->head = list->tail = NULL;
+}
+
+void drvmgr_list_add_head(struct drvmgr_list *list, void *entry)
+{
+	LIST_FIELD(list, entry) = list->head;
+	if (list->head == NULL)
+		list->tail = entry;
+	list->head = entry;
+}
+
+void drvmgr_list_add_tail(struct drvmgr_list *list, void *entry)
+{
+	if (list->tail == NULL)
+		list->head = entry;
+	else
+		LIST_FIELD(list, list->tail) = entry;
+	LIST_FIELD(list, entry) = NULL;
+	list->tail = entry;
+}
+
+void drvmgr_list_remove_head(struct drvmgr_list *list)
+{
+	list->head = LIST_FIELD(list, list->head);
+	if (list->head == NULL)
+		list->tail = NULL;
+}
+
+void drvmgr_list_remove(struct drvmgr_list *list, void *entry)
+{
+	void **prevptr = &list->head;
+	void *curr, *prev;
+
+	prev = NULL;
+	curr = list->head;
+	while (curr != entry) {
+		prev = curr;
+		prevptr = &LIST_FIELD(list, curr);
+		curr = LIST_FIELD(list, curr);
+	}
+	*prevptr = LIST_FIELD(list, entry);
+	if (list->tail == entry)
+		list->tail = prev;
+}
diff --git a/cpukit/libdrvmgr/drvmgr_list.h b/cpukit/libdrvmgr/drvmgr_list.h
new file mode 100644
index 0000000..6f4b98e
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_list.h
@@ -0,0 +1,79 @@
+/* Linked list help functions used by driver manager.
+ *
+ * COPYRIGHT (c) 2009.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+/*
+ * Help functions for the Driver Manager. Implements a singly linked list
+ * with head and tail pointers for fast insertions/deletions to head and
+ * tail in list.
+ */
+
+#ifndef _DRVIVER_MANAGER_LIST_H_
+#define _DRVIVER_MANAGER_LIST_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*! List description, Singly link list with head and tail pointers. */
+struct drvmgr_list {
+	void	*head;	/*!< First entry in queue */
+	void	*tail;	/*!< Last entry in queue */
+	int	ofs;	/*!< Offset into head and tail to find next field */
+};
+
+/* Static initialization of list */
+#define LIST_INITIALIZER(type, field) {NULL, NULL, offsetof(type, field)}
+
+/* Return the first element in list */
+#define LIST_HEAD(list, type) ((type *)(list)->head)
+
+/* Return the last element in list */
+#define LIST_TAIL(list, type) ((type *)(list)->tail)
+
+/* Get the next pointer of an entry */
+#define LIST_FIELD(list, entry) (*(void **)((char *)(entry) + (list)->ofs))
+
+/* Return the next emlement in list */
+#define LIST_NEXT(list, entry, type) ((type *)(LIST_FIELD(list, entry)))
+
+/* Iterate through all entries in list */
+#define LIST_FOR_EACH(list, entry, type) \
+	for (entry = LIST_HEAD(list, type); \
+	     entry; \
+	     entry = LIST_NEXT(list, entry, type))
+
+/*! Initialize a list during runtime
+ *
+ * \param list    The list to initialize
+ * \param offset  The number of bytes into the entry structure the next pointer
+ *                is found
+ */
+extern void drvmgr_list_init(struct drvmgr_list *list, int offset);
+
+/*! Clear list */
+extern void drvmgr_list_empty(struct drvmgr_list *list);
+
+/*! Add entry to front of list */
+extern void drvmgr_list_add_head(struct drvmgr_list *list, void *entry);
+
+/*! Add entry to end of list */
+extern void drvmgr_list_add_tail(struct drvmgr_list *list, void *entry);
+
+/*! Remove entry from front of list */
+extern void drvmgr_list_remove_head(struct drvmgr_list *list);
+
+/*! Remove entry from anywhere in list */
+extern void drvmgr_list_remove(struct drvmgr_list *list, void *entry);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libdrvmgr/drvmgr_lock.c b/cpukit/libdrvmgr/drvmgr_lock.c
new file mode 100644
index 0000000..d6601d3
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_lock.c
@@ -0,0 +1,38 @@
+/* Driver Manager Internal locking implementation
+ *
+ * COPYRIGHT (c) 2009.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <drvmgr/drvmgr.h>
+#include "drvmgr_internal.h"
+
+void _DRV_Manager_Lock(void)
+{
+	rtems_semaphore_obtain(drv_mgr.lock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+}
+
+void _DRV_Manager_Unlock(void)
+{
+	rtems_semaphore_release(drv_mgr.lock);
+}
+
+int _DRV_Manager_Init_Lock(void)
+{
+	int rc;
+
+	rc = rtems_semaphore_create(
+		rtems_build_name('D', 'R', 'V', 'M'),
+		1,
+		RTEMS_DEFAULT_ATTRIBUTES,
+		0,
+		&drv_mgr.lock);
+	if (rc != RTEMS_SUCCESSFUL)
+		return -1;
+	return 0;
+}
diff --git a/cpukit/libdrvmgr/drvmgr_print.c b/cpukit/libdrvmgr/drvmgr_print.c
new file mode 100644
index 0000000..c36abfe
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_print.c
@@ -0,0 +1,457 @@
+/* Driver Manager Information printing Interface Implementation
+ *
+ * COPYRIGHT (c) 2009.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+/*
+ *  These functions print stuff about the driver manager, what devices were
+ *  found and were united with a driver, the Bus topology, memory taken, etc.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <drvmgr/drvmgr.h>
+#include "drvmgr_internal.h"
+
+typedef void (*fun_ptr)(void);
+
+static int print_dev_found(struct drvmgr_dev *dev, void *arg)
+{
+	char **pparg = arg;
+
+	if (pparg && *pparg) {
+		printf(*pparg);
+		*pparg = NULL;
+	}
+
+	printf(" DEV %p  %s on bus %p\n", dev,
+		dev->name ? dev->name : "NO_NAME", dev->parent);
+
+	return 0; /* Continue to next device */
+}
+
+void drvmgr_print_devs(unsigned int options)
+{
+	struct rtems_driver_manager *mgr = &drv_mgr;
+	char *parg;
+
+	/* Print Drivers */
+	if (options & PRINT_DEVS_ASSIGNED) {
+		parg = " --- DEVICES ASSIGNED TO DRIVER ---\n";
+		drvmgr_for_each_listdev(&mgr->devices[DRVMGR_LEVEL_MAX],
+				DEV_STATE_UNITED, 0, print_dev_found, &parg);
+		if (parg != NULL)
+			printf("\n NO DEVICES WERE ASSIGNED A DRIVER\n");
+	}
+
+	if (options & PRINT_DEVS_UNASSIGNED) {
+		parg = "\n --- DEVICES WITHOUT DRIVER ---\n";
+		drvmgr_for_each_listdev(&mgr->devices_inactive, 0,
+			DEV_STATE_UNITED, print_dev_found, &parg);
+		if (parg != NULL)
+			printf("\n NO DEVICES WERE WITHOUT DRIVER\n");
+	}
+
+	if (options & PRINT_DEVS_FAILED) {
+		parg = "\n --- DEVICES FAILED TO INITIALIZE ---\n";
+		drvmgr_for_each_listdev(&mgr->devices_inactive,
+			DEV_STATE_INIT_FAILED, 0, print_dev_found, &parg);
+		if (parg != NULL)
+			printf("\n NO DEVICES FAILED TO INITIALIZE\n");
+	}
+
+	if (options & PRINT_DEVS_IGNORED) {
+		parg = "\n --- DEVICES IGNORED ---\n";
+		drvmgr_for_each_listdev(&mgr->devices_inactive,
+			DEV_STATE_IGNORED, 0, print_dev_found, &parg);
+		if (parg != NULL)
+			printf("\n NO DEVICES WERE IGNORED\n");
+	}
+
+	printf("\n\n");
+}
+
+static int drvmgr_topo_func(struct drvmgr_dev *dev, void *arg)
+{
+	char prefix[32];
+	int depth = dev->parent->depth;
+
+	if (depth > 30)
+		return 0; /* depth more than 30 not supported */
+	memset(prefix, ' ', depth + 1);
+	prefix[depth + 1] = '\0';
+
+	printf(" %s|-> DEV  %p  %s\n", prefix, dev,
+		dev->name ? dev->name :  "NO_NAME");
+	return 0;
+}
+
+void drvmgr_print_topo(void)
+{
+	/* Print Bus topology */
+	printf(" --- BUS TOPOLOGY ---\n");
+	drvmgr_for_each_dev(drvmgr_topo_func, NULL, DRVMGR_FED_DF);
+	printf("\n\n");
+}
+
+/* Print the memory usage */
+void drvmgr_print_mem(void)
+{
+	struct rtems_driver_manager *mgr = &drv_mgr;
+	struct drvmgr_bus *bus;
+	struct drvmgr_dev *dev;
+	struct drvmgr_drv *drv;
+
+	struct drvmgr_bus_res *node;
+	struct drvmgr_drv_res *res;
+	struct drvmgr_key *key;
+
+	unsigned int busmem = 0;
+	unsigned int devmem = 0;
+	unsigned int drvmem = 0;
+	unsigned int resmem = 0;
+	unsigned int devprivmem = 0;
+
+	DRVMGR_LOCK_READ();
+
+	bus = BUS_LIST_HEAD(&mgr->buses[DRVMGR_LEVEL_MAX]);
+	while (bus) {
+		busmem += sizeof(struct drvmgr_bus);
+
+		/* Get size of resources on this bus */
+		node = bus->reslist;
+		while (node) {
+			resmem += sizeof(struct drvmgr_bus_res);
+
+			res = node->resource;
+			while (res->keys) {
+				resmem += sizeof(struct drvmgr_drv_res);
+
+				key = res->keys;
+				while (key->key_type != KEY_TYPE_NONE) {
+					resmem += sizeof
+						(struct drvmgr_key);
+					key++;
+				}
+				resmem += sizeof(struct drvmgr_key);
+				res++;
+			}
+
+			node = node->next;
+		}
+
+		bus = bus->next;
+	}
+
+	drv = DRV_LIST_HEAD(&mgr->drivers);
+	while (drv) {
+		drvmem += sizeof(struct drvmgr_drv);
+		drv = drv->next;
+	}
+
+	dev = DEV_LIST_HEAD(&mgr->devices[DRVMGR_LEVEL_MAX]);
+	while (dev) {
+		devmem += sizeof(struct drvmgr_dev);
+		if (dev->drv && dev->drv->dev_priv_size > 0)
+			devprivmem += dev->drv->dev_priv_size;
+		dev = dev->next;
+	}
+
+	DRVMGR_UNLOCK();
+
+	printf(" --- MEMORY USAGE ---\n");
+	printf(" BUS:          %d bytes\n", busmem);
+	printf(" DRV:          %d bytes\n", drvmem);
+	printf(" DEV:          %d bytes\n", devmem);
+	printf(" DEV private:  %d bytes\n", devprivmem);
+	printf(" RES:          %d bytes\n", resmem);
+	printf(" TOTAL:        %d bytes\n",
+			busmem + drvmem + devmem + devprivmem + resmem);
+	printf("\n\n");
+}
+
+/* Print the memory usage */
+void drvmgr_summary(void)
+{
+	struct rtems_driver_manager *mgr = &drv_mgr;
+	struct drvmgr_bus *bus;
+	struct drvmgr_dev *dev;
+	struct drvmgr_drv *drv;
+	int i, buscnt = 0, devcnt = 0, drvcnt = 0;
+
+	printf(" --- SUMMARY ---\n");
+
+	drv = DRV_LIST_HEAD(&mgr->drivers);
+	while (drv) {
+		drvcnt++;
+		drv = drv->next;
+	}
+	printf(" NUMBER OF DRIVERS:               %d\n", drvcnt);
+
+	DRVMGR_LOCK_READ();
+
+	for (i = 0; i <= DRVMGR_LEVEL_MAX; i++) {
+		buscnt = 0;
+		bus = BUS_LIST_HEAD(&mgr->buses[i]);
+		while (bus) {
+			buscnt++;
+			bus = bus->next;
+		}
+		if (buscnt > 0) {
+			printf(" NUMBER OF BUSES IN LEVEL[%d]:     %d\n",
+				i, buscnt);
+		}
+	}
+
+	for (i = 0; i <= DRVMGR_LEVEL_MAX; i++) {
+		devcnt = 0;
+		dev = DEV_LIST_HEAD(&mgr->devices[i]);
+		while (dev) {
+			devcnt++;
+			dev = dev->next;
+		}
+		if (devcnt > 0) {
+			printf(" NUMBER OF DEVS IN LEVEL[%d]:      %d\n",
+				i, devcnt);
+		}
+	}
+
+	DRVMGR_UNLOCK();
+
+	printf("\n\n");
+}
+
+static void print_info(void *p, char *str)
+{
+	printf("  ");
+	puts(str);
+}
+
+void drvmgr_info_dev(struct drvmgr_dev *dev, unsigned int options)
+{
+	if (!dev)
+		return;
+
+	printf(" -- DEVICE %p --\n", dev);
+	if (options & OPTION_DEV_GENINFO) {
+		printf("  PARENT BUS:  %p\n", dev->parent);
+		printf("  NAME:        %s\n", dev->name ? dev->name : "NO_NAME");
+		printf("  STATE:       0x%08x\n", dev->state);
+		if (dev->bus)
+			printf("  BRIDGE TO:   %p\n", dev->bus);
+		printf("  INIT LEVEL:  %d\n", dev->level);
+		printf("  ERROR:       %d\n", dev->error);
+		printf("  MINOR BUS:   %d\n", dev->minor_bus);
+		if (dev->drv) {
+			printf("  MINOR DRV:   %d\n", dev->minor_drv);
+			printf("  DRIVER:      %p (%s)\n", dev->drv,
+				dev->drv->name ? dev->drv->name : "NO_NAME");
+			printf("  PRIVATE:     %p\n", dev->priv);
+		}
+	}
+
+	if (options & OPTION_DEV_BUSINFO) {
+		printf("  --- DEVICE INFO FROM BUS DRIVER ---\n");
+		if (!dev->parent)
+			printf("  !! device has no parent bus !!\n");
+		else if (dev->parent->ops->info_dev)
+			dev->parent->ops->info_dev(dev, print_info, NULL);
+		else
+			printf("  Bus doesn't implement info_dev func\n");
+	}
+
+	if (options & OPTION_DEV_DRVINFO) {
+		if (dev->drv) {
+			printf("  --- DEVICE INFO FROM DEVICE DRIVER ---\n");
+			if (dev->drv->ops->info)
+				dev->drv->ops->info(dev, print_info, NULL, 0, 0);
+			else
+				printf("  Driver doesn't implement info func\n");
+		}
+	}
+}
+
+static void drvmgr_info_bus_map(struct drvmgr_map_entry *map)
+{
+	if (map == NULL)
+		printf("    Addresses mapped 1:1\n");
+	else if (map == DRVMGR_TRANSLATE_NO_BRIDGE)
+		printf("    No bridge in this direction\n");
+	else {
+		while (map->size != 0) {
+			printf("    0x%08lx-0x%08lx => 0x%08lx-0x%08lx  %s\n",
+				(unsigned long)map->from_adr,
+				(unsigned long)(map->from_adr + map->size - 1),
+				(unsigned long)map->to_adr,
+				(unsigned long)(map->to_adr + map->size - 1),
+				map->name ? map->name : "no label");
+			map++;
+		}
+	}
+}
+
+void drvmgr_info_bus(struct drvmgr_bus *bus, unsigned int options)
+{
+	struct drvmgr_dev *dev;
+
+	/* Print Driver */
+	printf("-- BUS %p --\n", bus);
+	printf("  BUS TYPE:    %d\n", bus->bus_type);
+	printf("  DEVICE:      %p (%s)\n", bus->dev,
+		bus->dev->name ? bus->dev->name : "NO_NAME");
+	printf("  OPS:         %p\n", bus->ops);
+	printf("  CHILDREN:    %d devices\n", bus->dev_cnt);
+	printf("  LEVEL:       %d\n", bus->level);
+	printf("  STATE:       0x%08x\n", bus->state);
+	printf("  ERROR:       %d\n", bus->error);
+
+	/* Print address mappings up- (to parent) and down- (from parent to
+	 * this bus) stream the bridge of this bus
+	 */
+	printf("  DOWN STREAMS BRIDGE MAPPINGS  (from parent to this bus)\n");
+	drvmgr_info_bus_map(bus->maps_down);
+	printf("  UP STREAMS BRIDGE MAPPINGS    (from this bus to parent)\n");
+	drvmgr_info_bus_map(bus->maps_up);
+
+	/* Print Devices on this bus? */
+	if (options & OPTION_BUS_DEVS) {
+		printf("  CHILDREN:\n");
+		DRVMGR_LOCK_READ();
+		dev = bus->children;
+		while (dev) {
+			printf("   |- DEV[%02d]: %p  %s\n", dev->minor_bus,
+				dev, dev->name ? dev->name : "NO_NAME");
+			dev = dev->next_in_bus;
+		}
+		DRVMGR_UNLOCK();
+	}
+}
+
+char *drv_ops_names[DRV_OPS_NUM] = {
+	"init[1]:",
+	"init[2]:",
+	"init[3]:",
+	"init[4]:",
+	"remove: ",
+	"info:   "
+};
+
+void drvmgr_info_drv(struct drvmgr_drv *drv, unsigned int options)
+{
+	struct drvmgr_dev *dev;
+	fun_ptr *ppfunc;
+	int i;
+
+	/* Print Driver */
+	printf(" -- DRIVER %p --\n", drv);
+	printf("  DRIVER ID:   0x%llx\n", drv->drv_id);
+	printf("  NAME:        %s\n", drv->name ? drv->name : "NO_NAME");
+	printf("  BUS TYPE:    %d\n", drv->bus_type);
+	printf("  OPERATIONS:\n");
+	for (i = 0, ppfunc = (fun_ptr *)&drv->ops->init[0]; i<DRV_OPS_NUM; i++)
+		printf("   %s    %p\n", drv_ops_names[i], ppfunc[i]);
+	printf("  NO. DEVICES: %d\n", drv->dev_cnt);
+
+	/* Print devices united with this driver? */
+	if (options & OPTION_DRV_DEVS) {
+		DRVMGR_LOCK_READ();
+		dev = drv->dev;
+		while (dev) {
+			printf("  DEV[%02d]:     %p  %s\n", dev->minor_drv,
+				dev, dev->name ? dev->name : "NO_NAME");
+			dev = dev->next_in_drv;
+		}
+		DRVMGR_UNLOCK();
+	}
+}
+
+void (*info_obj[3])(void *obj, unsigned int) = {
+	/* DRVMGR_OBJ_DRV */ (void (*)(void *, unsigned int))drvmgr_info_drv,
+	/* DRVMGR_OBJ_BUS */ (void (*)(void *, unsigned int))drvmgr_info_bus,
+	/* DRVMGR_OBJ_DEV */ (void (*)(void *, unsigned int))drvmgr_info_dev,
+};
+
+/* Get information about a device/bus/driver */
+void drvmgr_info(void *id, unsigned int options)
+{
+	int obj_type;
+	void (*func)(void *, unsigned int);
+
+	if (!id)
+		return;
+	obj_type = *(int *)id;
+	if ((obj_type < DRVMGR_OBJ_DRV) || (obj_type > DRVMGR_OBJ_DEV))
+		return;
+	func = info_obj[obj_type - 1];
+	func(id, options);
+}
+
+void drvmgr_info_devs_on_bus(struct drvmgr_bus *bus, unsigned int options)
+{
+	struct drvmgr_dev *dev;
+
+	/* Print All Devices on Bus */
+	printf("\n\n  -= All Devices on BUS %p =-\n\n", bus);
+	dev = bus->children;
+	while (dev) {
+		drvmgr_info_dev(dev, options);
+		puts("");
+		dev = dev->next_in_bus;
+	}
+
+	if ((options & OPTION_RECURSIVE) == 0)
+		return;
+
+	/* This device provides a bus, print the bus */
+	dev = bus->children;
+	while (dev) {
+		if (dev->bus)
+			drvmgr_info_devs_on_bus(dev->bus, options);
+		dev = dev->next_in_bus;
+	}
+}
+
+void drvmgr_info_devs(unsigned int options)
+{
+	struct rtems_driver_manager *mgr = &drv_mgr;
+	struct drvmgr_dev *dev;
+
+	/* Print device information of all devices and their child devices */
+	dev = &mgr->root_dev;
+	drvmgr_info_devs_on_bus(dev->bus, options);
+	printf("\n\n");
+}
+
+void drvmgr_info_drvs(unsigned int options)
+{
+	struct rtems_driver_manager *mgr = &drv_mgr;
+	struct drvmgr_drv *drv;
+
+	drv = DRV_LIST_HEAD(&mgr->drivers);
+	while (drv) {
+		drvmgr_info_drv(drv, options);
+		puts("\n");
+		drv = drv->next;
+	}
+}
+
+void drvmgr_info_buses(unsigned int options)
+{
+	struct rtems_driver_manager *mgr = &drv_mgr;
+	struct drvmgr_bus *bus;
+
+	bus = BUS_LIST_HEAD(&mgr->buses[DRVMGR_LEVEL_MAX]);
+	while (bus) {
+		drvmgr_info_bus(bus, options);
+		puts("\n");
+		bus = bus->next;
+	}
+}
diff --git a/cpukit/libdrvmgr/drvmgr_res.c b/cpukit/libdrvmgr/drvmgr_res.c
new file mode 100644
index 0000000..5f8598b
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_res.c
@@ -0,0 +1,102 @@
+/* Driver Manager Driver Resource Interface Implementation.
+ *
+ * COPYRIGHT (c) 2009.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <string.h>
+#include <drvmgr/drvmgr.h>
+
+/* Find all the resource keys for a device among all bus resources */
+int drvmgr_keys_get(struct drvmgr_dev *dev, struct drvmgr_key **keys)
+{
+	struct drvmgr_bus *bus;
+	struct drvmgr_bus_res *node;
+	struct drvmgr_drv_res *res;
+	uint64_t drv_id;
+
+	bus = dev->parent;
+	if (!bus || !dev->drv)
+		return -1;
+
+	drv_id = dev->drv->drv_id;
+
+	/* Loop all resource arrays */
+	node = bus->reslist;
+	while (node) {
+		/* Find driver ID in resource array */
+		res = &node->resource[0];
+		while (res->drv_id) {
+			if (res->drv_id == drv_id) {
+				/* Found resource matching driver, now check
+				 * that this resource is for this device.
+				 */
+				if (dev->minor_bus == res->minor_bus) {
+					/* Matching driver and core number */
+					if (keys)
+						*keys = res->keys;
+					return 0;
+				}
+			}
+			res++;
+		}
+		node = node->next;
+	}
+	if (keys)
+		*keys = NULL;
+	return 1;
+}
+
+/* Return key that matches key name */
+struct drvmgr_key *drvmgr_key_get(
+	struct drvmgr_key *keys,
+	char *key_name)
+{
+	struct drvmgr_key *key;
+
+	if (!keys)
+		return NULL;
+
+	key = keys;
+	while (key->key_type != KEY_TYPE_NONE) {
+		if (strcmp(key_name, key->key_name) == 0)
+			return key;
+		key++;
+	}
+	return NULL;
+}
+
+union drvmgr_key_value *drvmgr_key_val_get(
+	struct drvmgr_key *keys,
+	char *key_name,
+	int key_type)
+{
+	struct drvmgr_key *key_match;
+
+	key_match = drvmgr_key_get(keys, key_name);
+	if (key_match) {
+		/* Found key, put pointer to value into */
+		if ((key_type == -1) || (key_match->key_type == key_type))
+			return &key_match->key_value;
+	}
+	return NULL;
+}
+
+union drvmgr_key_value *drvmgr_dev_key_get(
+	struct drvmgr_dev *dev,
+	char *key_name,
+	int key_type)
+{
+	struct drvmgr_key *keys = NULL;
+
+	/* Find first entry in key array for the device */
+	if (drvmgr_keys_get(dev, &keys))
+		return NULL;
+
+	/* Find a specific key among the device keys */
+	return drvmgr_key_val_get(keys, key_name, key_type);
+}
diff --git a/cpukit/libdrvmgr/drvmgr_rw.c b/cpukit/libdrvmgr/drvmgr_rw.c
new file mode 100644
index 0000000..6530cdd
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_rw.c
@@ -0,0 +1,52 @@
+/* Driver Manager Read/Write Interface Implementation.
+ *
+ * COPYRIGHT (c) 2009.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <string.h>
+#include <drvmgr/drvmgr.h>
+
+/* Set a range of memory in 128 byte chunks.
+ * This call will take 128 bytes for buffer on stack
+ */
+void drvmgr_rw_memset(
+	void *dstadr,
+	int c,
+	size_t n,
+	void *a,
+	drvmgr_wmem_arg wmem
+	)
+{
+	unsigned long long buf[16+1]; /* Extra bytes after data are reserved
+				       * for optimizations by write_mem */
+	int txlen;
+	char *adr;
+
+	if (n <= 0)
+		return;
+
+	if (n > sizeof(unsigned long long)*16)
+		txlen = sizeof(unsigned long long)*16;
+	else
+		txlen = n;
+
+	memset(buf, c, txlen);
+
+	adr = dstadr;
+	do {
+		wmem(adr, (const void *)&buf[0], txlen, a);
+		adr += txlen;
+		n -= txlen;
+
+		/* next length to transmitt */
+		if (n > 16*sizeof(unsigned long long))
+			txlen = 16*sizeof(unsigned long long);
+		else
+			txlen = n;
+	} while (n > 0);
+}
diff --git a/cpukit/libdrvmgr/drvmgr_translate.c b/cpukit/libdrvmgr/drvmgr_translate.c
new file mode 100644
index 0000000..7febf77
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_translate.c
@@ -0,0 +1,149 @@
+/* Driver Manager Driver Translate Interface Implementation
+ *
+ * COPYRIGHT (c) 2010.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+/*
+ * Used by device drivers. The functions rely on that the parent bus driver
+ * has implemented the neccessary operations correctly.
+ *
+ * The translate functions are used to translate addresses between buses
+ * for DMA cores located on a "remote" bus, or for memory-mapped obtaining
+ * an address that can be used to access an remote bus.
+ *
+ * For example, PCI I/O might be memory-mapped at the PCI Host bridge,
+ * say address 0xfff10000-0xfff1ffff is mapped to the PCI I/O address
+ * of 0x00000000-0x0000ffff. The PCI Host bridge driver may then set up
+ * a map so that a driver that get PCI address 0x100 can translate that
+ * into 0xfff10100.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <drvmgr/drvmgr.h>
+#include "drvmgr_internal.h"
+
+unsigned int drvmgr_translate_bus(
+	struct drvmgr_bus *from,
+	struct drvmgr_bus *to,
+	int reverse,
+	void *src_address,
+	void **dst_address)
+{
+	struct drvmgr_bus *path[16];
+	int dir, levels, i;
+	void *dst, *from_adr, *to_adr;
+	struct drvmgr_map_entry *map;
+	struct drvmgr_bus *bus;
+	unsigned int sz;
+	struct drvmgr_bus *bus_bot, *bus_top;
+
+	dst = src_address;
+	sz = 0xffffffff;
+
+	if (from == to) /* no need translating addresses when on same bus */
+		goto out;
+
+	/* Always find translation path from remote bus towards root bus. All
+	 * buses have root bus has parent at some level
+	 */
+	if (from->depth > to->depth) {
+		bus_bot = from;
+		bus_top = to;
+		dir = 0;
+	} else {
+		bus_bot = to;
+		bus_top = from;
+		dir = 1;
+	}
+	levels = bus_bot->depth - bus_top->depth;
+	if (levels >= 16)
+		return 0; /* Does not support such a big depth */
+	i = 0;
+	while ((bus_bot != NULL) && bus_bot != bus_top) {
+		if (dir)
+			path[(levels - 1) - i] = bus_bot;
+		else
+			path[i] = bus_bot;
+		i++;
+		bus_bot = bus_bot->dev->parent;
+	}
+	if (bus_bot == NULL)
+		return 0; /* from -> to is not linearly connected */
+
+	for (i = 0; i < levels; i++) {
+		bus = path[i];
+
+		if ((dir && reverse) || (!dir && !reverse))
+			map = bus->maps_up;
+		else
+			map = bus->maps_down;
+
+		if (map == NULL)
+			continue; /* No translation needed - 1:1 mapping */
+
+		if (map == DRVMGR_TRANSLATE_NO_BRIDGE) {
+			sz = 0;
+			break; /* No bridge interface in this direction */
+		}
+
+		while (map->size != 0) {
+			if (reverse) {
+				/* Opposite direction */
+				from_adr = map->to_adr;
+				to_adr = map->from_adr;
+			} else {
+				from_adr = map->from_adr;
+				to_adr = map->to_adr;
+			}
+
+			if ((dst >= from_adr) &&
+			    (dst <= (from_adr + (map->size - 1)))) {
+				if (((from_adr + (map->size - 1)) - dst) < sz)
+					sz = (from_adr + (map->size - 1)) - dst;
+				dst = (dst - from_adr) + to_adr;
+				break;
+			}
+			map++;
+		}
+		/* quit if no matching translation information */
+		if (map->size == 0) {
+			sz = 0;
+			break;
+		}
+	}
+
+out:
+	if (dst_address)
+		*dst_address = dst;
+
+	return sz;
+}
+
+unsigned int drvmgr_translate(
+	struct drvmgr_dev *dev,
+	unsigned int options,
+	void *src_address,
+	void **dst_address)
+{
+	struct drvmgr_bus *to, *from;
+	int rev = 0;
+
+	rev = (~options) & 1;
+	if ((options == CPUMEM_TO_DMA) || (options == DMAMEM_FROM_CPU)) {
+		from = drv_mgr.root_dev.bus;
+		to = dev->parent;
+	} else { /* CPUMEM_FROM_DMA || DMAMEM_TO_CPU */
+		from = dev->parent;
+		to = drv_mgr.root_dev.bus;
+	}
+
+	return drvmgr_translate_bus(from, to, rev, src_address, dst_address);
+}
diff --git a/cpukit/libdrvmgr/drvmgr_translate_check.c b/cpukit/libdrvmgr/drvmgr_translate_check.c
new file mode 100644
index 0000000..c882b88
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_translate_check.c
@@ -0,0 +1,35 @@
+/* Driver Manager Driver Translate Interface Implementation
+ *
+ * COPYRIGHT (c) 2010.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <drvmgr/drvmgr.h>
+
+/* Calls drvmgr_translate() to translate an address range and check the result,
+ * a printout is generated if the check fails. See paramters of
+ * drvmgr_translate().
+ * If size=0 only the starting address is not checked.
+ */
+int drvmgr_translate_check(
+	struct drvmgr_dev *dev,
+	unsigned int options,
+	void *src_address,
+	void **dst_address,
+	unsigned int size)
+{
+	unsigned int max;
+
+	max = drvmgr_translate(dev, options, src_address, dst_address);
+	if (max == 0 || (max < size && (size != 0))) {
+		printk(" ### dev %p (%s) failed mapping %p\n",
+			dev, dev->name ? dev->name : "unnamed", src_address);
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/cpukit/libdrvmgr/drvmgr_unregister.c b/cpukit/libdrvmgr/drvmgr_unregister.c
new file mode 100644
index 0000000..ef5260a
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_unregister.c
@@ -0,0 +1,186 @@
+/* Driver Manager Device Unregister (removal) implementation
+ *
+ * COPYRIGHT (c) 2011.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <stdlib.h>
+
+#include <drvmgr/drvmgr.h>
+#include <drvmgr/drvmgr_list.h>
+#include "drvmgr_internal.h"
+
+/* Unregister all children on a bus.
+ *
+ * This function is called from the bus driver, from a "safe" state where
+ * devices will not be added or removed on this particular bus at this time
+ */
+int drvmgr_children_unregister(struct drvmgr_bus *bus)
+{
+	int err;
+
+	while (bus->children != NULL) {
+		err = drvmgr_dev_unregister(bus->children);
+		if (err != DRVMGR_OK) {
+			/* An error occured */
+			bus->children->error = err;
+			return err;
+		}
+	}
+
+	return DRVMGR_OK;
+}
+
+/* Unregister a BUS and all it's devices.
+ *
+ * It is up to the bus driver to remove all it's devices, either manually
+ * one by one calling drvmgr_dev_unregister(), or by letting the driver
+ * manager unregister all children by calling drvmgr_children_unregister().
+ */
+int drvmgr_bus_unregister(struct drvmgr_bus *bus)
+{
+	struct rtems_driver_manager *mgr = &drv_mgr;
+	struct drvmgr_list *list;
+
+	if (bus->ops->remove == NULL)
+		return DRVMGR_ENOSYS;
+
+	/* Call Bus driver to clean things up, it must remove all children */
+	bus->error = bus->ops->remove(bus);
+	if (bus->error != DRVMGR_OK)
+		return bus->error;
+	/* Check that bus driver has done its job and removed all children */
+	if (bus->children != NULL)
+		return DRVMGR_FAIL;
+	/* Remove References to bus */
+	bus->dev->bus = NULL;
+
+	DRVMGR_LOCK_WRITE();
+
+	/* Remove bus from bus-list */
+	if (bus->state & BUS_STATE_LIST_INACTIVE)
+		list = &mgr->buses_inactive;
+	else
+		list = &mgr->buses[bus->level];
+	drvmgr_list_remove(list, bus);
+
+	DRVMGR_UNLOCK();
+
+	/* All references to this bus has been removed at this point */
+	free(bus);
+
+	return DRVMGR_OK;
+}
+
+/* Separate Driver and Device from each other */
+int drvmgr_dev_drv_separate(struct drvmgr_dev *dev)
+{
+	struct rtems_driver_manager *mgr = &drv_mgr;
+	struct drvmgr_dev *subdev, **pprev;
+	int rc;
+
+	/* Remove children if this device exports a bus of devices. All
+	 * children must be removed first as they depend upon the bus
+	 * services this bridge provide.
+	 */
+	if (dev->bus) {
+		rc = drvmgr_bus_unregister(dev->bus);
+		if (rc != DRVMGR_OK)
+			return rc;
+	}
+
+	if (dev->drv == NULL)
+		return DRVMGR_OK;
+
+	/* Remove device by letting assigned driver take care of hardware
+	 * issues
+	 */
+	if (!dev->drv->ops->remove) {
+		/* No remove function is considered severe when someone
+		 * is trying to remove the device
+		 */
+		return DRVMGR_ENOSYS;
+	}
+	dev->error = dev->drv->ops->remove(dev);
+	if (dev->error != DRVMGR_OK)
+		return DRVMGR_FAIL;
+
+	DRVMGR_LOCK_WRITE();
+
+	/* Delete device from driver's device list */
+	pprev = &dev->drv->dev;
+	subdev = dev->drv->dev;
+	while (subdev != dev) {
+		pprev = &subdev->next_in_drv;
+		subdev = subdev->next_in_drv;
+	}
+	*pprev = subdev->next_in_drv;
+	dev->drv->dev_cnt--;
+
+	/* Move device to inactive list */
+	drvmgr_list_remove(&mgr->devices[dev->level], dev);
+	dev->level = 0;
+	dev->state &= ~(DEV_STATE_UNITED|DEV_STATE_INIT_DONE);
+	dev->state |= DEV_STATE_LIST_INACTIVE;
+	drvmgr_list_add_tail(&mgr->devices_inactive, dev);
+
+	DRVMGR_UNLOCK();
+
+	/* Free Device Driver Private memory if allocated previously by
+	 * Driver manager.
+	 */
+	if (dev->drv->dev_priv_size && dev->priv) {
+		free(dev->priv);
+		dev->priv = NULL;
+	}
+	dev->drv = NULL;
+
+	return DRVMGR_OK;
+}
+
+/* Unregister device,
+ *  - let assigned driver handle deletion
+ *  - remove from device list
+ *  - remove from driver list
+ *  - remove from bus list
+ */
+int drvmgr_dev_unregister(struct drvmgr_dev *dev)
+{
+	struct rtems_driver_manager *mgr = &drv_mgr;
+	struct drvmgr_dev *subdev, **pprev;
+	int err;
+
+	/* Separate device from driver, if the device is united with a driver.
+	 *
+	 * If this device is a bridge all child buses/devices are also removed.
+	 */
+	err = drvmgr_dev_drv_separate(dev);
+	if (err != DRVMGR_OK)
+		return err;
+
+	DRVMGR_LOCK_WRITE();
+
+	/* Remove it from inactive list */
+	drvmgr_list_remove(&mgr->devices_inactive, dev);
+
+	/* Remove device from parent bus list (no check if dev not in list) */
+	pprev = &dev->parent->children;
+	subdev = dev->parent->children;
+	while (subdev != dev) {
+		pprev = &subdev->next_in_bus;
+		subdev = subdev->next_in_bus;
+	}
+	*pprev = subdev->next_in_bus;
+	dev->parent->dev_cnt--;
+
+	DRVMGR_UNLOCK();
+
+	/* All references to this device has been removed at this point */
+	free(dev);
+
+	return DRVMGR_OK;
+}
diff --git a/cpukit/preinstall.am b/cpukit/preinstall.am
index b125b2f..806e4bc 100644
--- a/cpukit/preinstall.am
+++ b/cpukit/preinstall.am
@@ -514,3 +514,20 @@ $(PROJECT_INCLUDE)/rtems/fsmount.h: libmisc/fsmount/fsmount.h $(PROJECT_INCLUDE)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/fsmount.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/fsmount.h
 
+$(PROJECT_INCLUDE)/drvmgr/$(dirstamp):
+	@$(MKDIR_P) $(PROJECT_INCLUDE)/drvmgr
+	@: > $(PROJECT_INCLUDE)/drvmgr/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/drvmgr/$(dirstamp)
+
+$(PROJECT_INCLUDE)/drvmgr/drvmgr.h: libdrvmgr/drvmgr.h $(PROJECT_INCLUDE)/drvmgr/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/drvmgr/drvmgr.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/drvmgr/drvmgr.h
+
+$(PROJECT_INCLUDE)/drvmgr/drvmgr_confdefs.h: libdrvmgr/drvmgr_confdefs.h $(PROJECT_INCLUDE)/drvmgr/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/drvmgr/drvmgr_confdefs.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/drvmgr/drvmgr_confdefs.h
+
+$(PROJECT_INCLUDE)/drvmgr/drvmgr_list.h: libdrvmgr/drvmgr_list.h $(PROJECT_INCLUDE)/drvmgr/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/drvmgr/drvmgr_list.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/drvmgr/drvmgr_list.h
+
diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h
index cce961c..1bb630b 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -144,6 +144,15 @@ const rtems_libio_helper rtems_fs_init_helper =
  */
 #define CONFIGURE_LIBIO_POSIX_KEYS 1
 
+/**
+ *  Driver Manager Configuration
+ */
+#ifdef RTEMS_DRVMGR_STARTUP
+  #define CONFIGURE_DRVMGR_SEMAPHORES 1
+#else
+  #define CONFIGURE_DRVMGR_SEMAPHORES 0
+#endif
+
 #ifdef CONFIGURE_INIT
   rtems_libio_t rtems_libio_iops[CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS];
 
@@ -1863,7 +1872,7 @@ const rtems_libio_helper rtems_fs_init_helper =
     (CONFIGURE_MAXIMUM_SEMAPHORES + CONFIGURE_LIBIO_SEMAPHORES + \
       CONFIGURE_TERMIOS_SEMAPHORES + CONFIGURE_LIBBLOCK_SEMAPHORES + \
       CONFIGURE_SEMAPHORES_FOR_FILE_SYSTEMS + \
-      CONFIGURE_NETWORKING_SEMAPHORES)
+      CONFIGURE_NETWORKING_SEMAPHORES + CONFIGURE_DRVMGR_SEMAPHORES)
 
   #if !defined(RTEMS_SMP) || \
     !defined(CONFIGURE_MAXIMUM_MRSP_SEMAPHORES)
diff --git a/cpukit/sapi/src/exinit.c b/cpukit/sapi/src/exinit.c
index 235ba77..ba71ec4 100644
--- a/cpukit/sapi/src/exinit.c
+++ b/cpukit/sapi/src/exinit.c
@@ -56,6 +56,10 @@
 #include <rtems/rtems/rtemsapi.h>
 #include <rtems/posix/posixapi.h>
 
+#ifdef RTEMS_DRVMGR_STARTUP
+  #include <drvmgr/drvmgr.h>
+#endif
+
 Objects_Information *_Internal_Objects[ OBJECTS_INTERNAL_CLASSES_LAST + 1 ];
 
 void rtems_initialize_data_structures(void)
@@ -161,6 +165,9 @@ void rtems_initialize_data_structures(void)
 
 void rtems_initialize_before_drivers(void)
 {
+  #ifdef RTEMS_DRVMGR_STARTUP
+  _DRV_Manager_initialization();
+  #endif
 
   #if defined(RTEMS_MULTIPROCESSING)
     _MPCI_Create_server();
@@ -182,8 +189,64 @@ void rtems_initialize_device_drivers(void)
    *  NOTE:  The MPCI may be build upon a device driver.
    */
 
+  #ifdef RTEMS_DRVMGR_STARTUP
+  /* BSPs has already registered their "root bus" driver in the
+   * bsp_predriver hook or so.
+   *
+   * Init Drivers to Level 1, constraints:
+   *   - Interrupts and system clock timer does not work.
+   *   - malloc() work, however other memory services may not
+   *     have been initialized yet.
+   *   - initializes most basic stuff
+   *
+   * Typical setup in Level 1:
+   *   - Find most devices in system, do PCI scan and configuration.
+   *   - Reset hardware if needed.
+   *   - Install IRQ driver
+   *   - Install Timer driver
+   *   - Install console driver and debug printk()
+   *   - Install extra memory.
+   */
+  _DRV_Manager_init_level(1);
+  bsp_driver_level_hook(1);
+  #endif
+
+  /* Initialize I/O drivers. 
+   *
+   * Driver Manager note:
+   * All drivers may not be registered yet. Drivers will dynamically
+   * be initialized when registered in level 2,3 and 4.
+   */
   _IO_Initialize_all_drivers();
 
+  #ifdef RTEMS_DRVMGR_STARTUP
+  /* Init Drivers to Level 2, constraints:
+   *  - Interrupts can be registered and enabled.
+   *  - System Clock is running
+   *  - Console may be used.
+   *
+   * This is typically where drivers are initialized
+   * for the first time.
+   */
+  _DRV_Manager_init_level(2);
+  bsp_driver_level_hook(2);
+
+  /* Init Drivers to Level 3 
+   * 
+   * This is typically where normal drivers are initialized
+   * for the second time, they may depend on other drivers
+   * API inited in level 2
+   */
+  _DRV_Manager_init_level(3);
+  bsp_driver_level_hook(3);
+
+  /* Init Drivers to Level 4,
+   * Init drivers that depend on services initialized in Level 3
+   */
+  _DRV_Manager_init_level(4);
+  bsp_driver_level_hook(4);
+  #endif
+
   #if defined(RTEMS_MULTIPROCESSING)
     if ( _System_state_Is_multiprocessing ) {
       _MPCI_Initialization();
diff --git a/cpukit/wrapup/Makefile.am b/cpukit/wrapup/Makefile.am
index c61ab05..7ae7d8a 100644
--- a/cpukit/wrapup/Makefile.am
+++ b/cpukit/wrapup/Makefile.am
@@ -62,10 +62,9 @@ TMP_LIBS += ../libmisc/libutf8proc.a
 endif
 
 TMP_LIBS += ../libmisc/libuuid.a
-
 TMP_LIBS += ../libi2c/libi2c.a
-
 TMP_LIBS += ../libpci/libpci.a
+TMP_LIBS += ../libdrvmgr/libdrvmgr.a
 
 if LIBNETWORKING
 TMP_LIBS += ../libnetworking/libnetworking.a
-- 
1.7.0.4




More information about the devel mailing list