Index: c/src/lib/libbsp/powerpc/mpc55xxevb/ChangeLog
===================================================================
--- c/src/lib/libbsp/powerpc/mpc55xxevb/ChangeLog	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libbsp/powerpc/mpc55xxevb/ChangeLog	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -1,2 +1,11 @@
+2009-07-20	Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+	* clock/clock-config.c, include/smsc9218i.h, network/smsc9218i.c: New
+	files.
+	* network/network.c: Removed file.
+	* Makefile.am, README, bsp_specs, preinstall.am, include/bsp.h,
+	startup/bspstart.c, startup/sd-card-init.c, tests/tests.c: Changes
+	throughout.
+
 2009-07-16	Joel Sherrill <joel.sherrill@oarcorp.com>
 
Index: c/src/lib/libbsp/powerpc/mpc55xxevb/Makefile.am
===================================================================
--- c/src/lib/libbsp/powerpc/mpc55xxevb/Makefile.am	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libbsp/powerpc/mpc55xxevb/Makefile.am	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -37,5 +37,8 @@
 include_bsp_HEADERS = include/mpc55xxevb.h \
     include/irq-config.h \
+    include/smsc9218i.h \
     ../../shared/include/irq-generic.h \
+    ../../shared/include/irq-info.h \
+    ../../shared/include/utility.h \
     ../shared/include/tictac.h
 
@@ -46,9 +49,11 @@
 
 # clock
-libbsp_a_SOURCES += ../shared/clock/clock.c
+libbsp_a_SOURCES += clock/clock-config.c
 
 # irq_generic
 libbsp_a_SOURCES += ../../shared/src/irq-generic.c \
-    ../../shared/src/irq-legacy.c
+    ../../shared/src/irq-legacy.c \
+    ../../shared/src/irq-info.c \
+    ../../shared/src/irq-shell.c
 
 # tests
@@ -61,5 +66,5 @@
 if HAS_NETWORKING
 noinst_PROGRAMS += network.rel
-network_rel_SOURCES = network/network.c
+network_rel_SOURCES = network/smsc9218i.c
 network_rel_CPPFLAGS = $(AM_CPPFLAGS) -D__INSIDE_RTEMS_BSD_TCPIP_STACK__ -D__BSD_VISIBLE
 network_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
@@ -74,4 +79,5 @@
     ../../../libcpu/@RTEMS_CPU@/@RTEMS_CPU_MODEL@/irq.rel \
     ../../../libcpu/@RTEMS_CPU@/@RTEMS_CPU_MODEL@/edma.rel \
+    ../../../libcpu/@RTEMS_CPU@/@RTEMS_CPU_MODEL@/emios.rel \
     ../../../libcpu/@RTEMS_CPU@/@RTEMS_CPU_MODEL@/dspi.rel \
     ../../../libcpu/@RTEMS_CPU@/@RTEMS_CPU_MODEL@/esci.rel \
Index: c/src/lib/libbsp/powerpc/mpc55xxevb/README
===================================================================
--- c/src/lib/libbsp/powerpc/mpc55xxevb/README	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libbsp/powerpc/mpc55xxevb/README	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -9,5 +9,4 @@
 COPROCESSORS:       N/A
 MODE:               32 bit mode
-DEBUG MONITOR:      BAM
 
 PERIPHERALS
@@ -22,4 +21,5 @@
 SCSI:               N/A
 NETWORKING:         FEC (not yet supported)
+                    SMSC9218I (external)
 SPI:                DSPI
 
@@ -27,5 +27,5 @@
 ==================
 
-CLOCK DRIVER:       Book E decrementer
+CLOCK DRIVER:       EMIOS channel 23
 IOSUPP DRIVER:      N/A
 SHMSUPP:            N/A
@@ -48,5 +48,5 @@
 BUS WIDTH:          32 bit Flash, 32 bit SDRAM
 FLASH:              3 MByte
-RAM:                128 kByte SDRAM 
+INTERNAL RAM:       128 kByte SDRAM 
 EXTERNAL RAM:       512 kByte SDRAM 
 
Index: c/src/lib/libbsp/powerpc/mpc55xxevb/bsp_specs
===================================================================
--- c/src/lib/libbsp/powerpc/mpc55xxevb/bsp_specs	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libbsp/powerpc/mpc55xxevb/bsp_specs	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -5,8 +5,8 @@
 *startfile:
 %{!qrtems: %(old_startfile)} \
-%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s start.o%s}}
+%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s start.o%s}}
 
 *endfile:
-%{!qrtems: %(old_endfile)} %{qrtems: ecrtn.o%s}
+%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s}
 
 *link:
Index: c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c
===================================================================
--- c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
+++ c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -0,0 +1,150 @@
+/**
+ * @file
+ *
+ * @ingroup mpc55xx
+ *
+ * @brief Clock driver configuration.
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * 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 <mpc55xx/regs.h>
+#include <mpc55xx/emios.h>
+
+#include <rtems.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+
+#define RTEMS_STATUS_CHECKS_USE_PRINTK
+
+#include <rtems/status-checks.h>
+
+#define MPC55XX_CLOCK_EMIOS_CHANNEL (MPC55XX_EMIOS_CHANNEL_NUMBER - 1)
+
+/* This is defined in clockdrv_shell.h */
+rtems_isr Clock_isr( rtems_vector_number vector);
+
+#define Clock_driver_support_at_tick() \
+ do { \
+    union EMIOS_CSR_tag csr = MPC55XX_ZERO_FLAGS; \
+    csr.B.FLAG = 1; \
+    EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL].CSR.R = csr.R; \
+ } while (0)
+
+static void mpc55xx_clock_handler_install( void)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  sc = mpc55xx_interrupt_handler_install(
+    MPC55XX_IRQ_EMIOS_GET_REQUEST( MPC55XX_CLOCK_EMIOS_CHANNEL),
+    "clock",
+    RTEMS_INTERRUPT_UNIQUE,
+    MPC55XX_INTC_MIN_PRIORITY,
+    (rtems_interrupt_handler) Clock_isr,
+    NULL
+  );
+  RTEMS_CHECK_SC_VOID( sc, "install clock interrupt handler");
+}
+
+static void mpc55xx_clock_initialize( void)
+{
+  volatile struct EMIOS_CH_tag *regs = &EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL];
+  union EMIOS_CCR_tag ccr = MPC55XX_ZERO_FLAGS;
+  union EMIOS_CSR_tag csr = MPC55XX_ZERO_FLAGS;
+  unsigned prescaler = mpc55xx_emios_global_prescaler();
+  uint64_t interval = ((uint64_t) bsp_clock_speed
+    * (uint64_t) rtems_configuration_get_microseconds_per_tick()) / 1000000;
+
+  /* Apply prescaler */
+  if (prescaler > 0) {
+    interval /= (uint64_t) prescaler;
+  } else {
+    RTEMS_SYSLOG_ERROR( "unexpected global eMIOS prescaler\n");
+  }
+
+  /* Check interval */
+  if (interval == 0 || interval > MPC55XX_EMIOS_VALUE_MAX) {
+    interval = MPC55XX_EMIOS_VALUE_MAX;
+    RTEMS_SYSLOG_ERROR( "clock timer interval out of range\n");
+  }
+
+  /* Configure eMIOS channel */
+  
+  /* Set channel in GPIO mode */
+  ccr.B.MODE = MPC55XX_EMIOS_MODE_GPIO_INPUT;
+  regs->CCR.R = ccr.R;
+  
+  /* Clear status flags */
+  csr.B.OVR = 1;
+  csr.B.OVFL = 1;
+  csr.B.FLAG = 1;
+  regs->CSR.R = csr.R;
+  
+  /* Set timer period */
+  regs->CADR.R = (uint32_t) interval - 1;
+  
+  /* Set unused registers */
+  regs->CBDR.R = 0;
+  regs->CCNTR.R = 0;
+  regs->ALTCADR.R = 0;
+  
+  /* Set control register */
+  ccr.B.MODE = MPC55XX_EMIOS_MODE_MC_UP_INT_CLK;
+  ccr.B.UCPREN = 1;
+  ccr.B.FEN = 1;
+  ccr.B.FREN = 1;
+  regs->CCR.R = ccr.R;
+}
+
+static void mpc55xx_clock_cleanup( void)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  volatile struct EMIOS_CH_tag *regs = &EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL];
+  union EMIOS_CCR_tag ccr = MPC55XX_ZERO_FLAGS;
+
+  /* Set channel in GPIO mode */
+  ccr.B.MODE = MPC55XX_EMIOS_MODE_GPIO_INPUT;
+  regs->CCR.R = ccr.R;
+
+  /* Remove interrupt handler */
+  sc = rtems_interrupt_handler_remove(
+    MPC55XX_IRQ_EMIOS_GET_REQUEST( MPC55XX_CLOCK_EMIOS_CHANNEL),
+    (rtems_interrupt_handler) Clock_isr,
+    NULL
+  );
+  RTEMS_CHECK_SC_VOID( sc, "remove clock interrupt handler");
+}
+
+static uint32_t mpc55xx_clock_nanoseconds_since_last_tick( void)
+{
+  uint64_t clicks = EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL].CCNTR.R;
+  uint64_t clock = bsp_clock_speed;
+  uint64_t ns = (clicks * 1000000000) / clock;
+  
+  return (uint32_t) ns;
+}
+ 
+#define Clock_driver_support_initialize_hardware() mpc55xx_clock_initialize()
+
+#define Clock_driver_support_install_isr( isr, old_isr) \
+  mpc55xx_clock_handler_install()
+
+#define Clock_driver_support_shutdown_hardware() mpc55xx_clock_cleanup()
+  
+#define Clock_driver_nanoseconds_since_last_tick \
+  mpc55xx_clock_nanoseconds_since_last_tick
+
+/* Include shared source clock driver code */
+#include "../../../../libbsp/shared/clockdrv_shell.h"
Index: c/src/lib/libbsp/powerpc/mpc55xxevb/include/bsp.h
===================================================================
--- c/src/lib/libbsp/powerpc/mpc55xxevb/include/bsp.h	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libbsp/powerpc/mpc55xxevb/include/bsp.h	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -44,5 +44,18 @@
 extern uint32_t bsp_clicks_per_usec;
 
-rtems_status_code mpc55xx_sd_card_init( void);
+rtems_status_code mpc55xx_sd_card_init( bool mount);
+
+/* Network driver configuration */
+
+struct rtems_bsdnet_ifconfig;
+
+int smsc9218i_attach_detach(
+  struct rtems_bsdnet_ifconfig *config,
+  int attaching
+);
+
+#define RTEMS_BSP_NETWORK_DRIVER_ATTACH smsc9218i_attach_detach
+
+#define RTEMS_BSP_NETWORK_DRIVER_NAME "eth0"
 
 #endif /* ASM */
Index: c/src/lib/libbsp/powerpc/mpc55xxevb/include/smsc9218i.h
===================================================================
--- c/src/lib/libbsp/powerpc/mpc55xxevb/include/smsc9218i.h	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
+++ c/src/lib/libbsp/powerpc/mpc55xxevb/include/smsc9218i.h	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -0,0 +1,795 @@
+/**
+ * @file
+ *
+ * @ingroup mpc55xx
+ *
+ * @brief SMSC - LAN9218i
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * rtems@embedded-brains.de
+ *
+ * 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.
+ */
+
+/**
+ * @name Memory Map
+ * @{                       
+ */
+
+typedef struct {
+  uint32_t rx_fifo_data;
+  uint32_t rx_fifo_data_aliases [7];
+  uint32_t tx_fifo_data;
+  uint32_t tx_fifo_data_aliases [7];
+  uint32_t rx_fifo_status;
+  uint32_t rx_fifo_status_peek;
+  uint32_t tx_fifo_status;
+  uint32_t tx_fifo_status_peek;
+  uint32_t id_rev;
+  uint32_t irq_cfg;
+  uint32_t int_sts;
+  uint32_t int_en;
+  uint32_t reserved_0;
+  uint32_t byte_test;
+  uint32_t fifo_int;
+  uint32_t rx_cfg;
+  uint32_t tx_cfg;
+  uint32_t hw_cfg;
+  uint32_t rx_dp_ctl;
+  uint32_t rx_fifo_inf;
+  uint32_t tx_fifo_inf;
+  uint32_t pmt_ctrl;
+  uint32_t gpio_cfg;
+  uint32_t gpt_cfg;
+  uint32_t gpt_cnt;
+  uint32_t reserved_1;
+  uint32_t word_swap;
+  uint32_t free_run;
+  uint32_t rx_drop;
+  uint32_t mac_csr_cmd;
+  uint32_t mac_csr_data;
+  uint32_t afc_cfg;
+  uint32_t e2p_cmd;
+  uint32_t e2p_data;
+} smsc9218i_registers;
+
+volatile smsc9218i_registers *const smsc9218i = (volatile smsc9218i_registers *) 0x3fff8000;
+
+/** @} */
+
+#define SMSC9218I_BIT_POS(pos) \
+  ((pos) > 15 ? \
+    ((pos) > 23 ? (pos) - 24 : (pos) - 8) \
+      : ((pos) > 7 ? (pos) + 8 : (pos) + 24))
+
+#define SMSC9218I_FLAG(pos) \
+  (1U << SMSC9218I_BIT_POS(pos))
+
+#define SMSC9218I_FIELD_8(val, pos) \
+  (((val) & 0xff) << SMSC9218I_BIT_POS(pos))
+
+#define SMSC9218I_GET_FIELD_8(reg, pos) \
+  (((reg) >> SMSC9218I_BIT_POS(pos)) & 0xff)
+
+#define SMSC9218I_FIELD_16(val, pos) \
+  (SMSC9218I_FIELD_8((val) >> 8, (pos) + 8) \
+    | SMSC9218I_FIELD_8((val), pos))
+
+#define SMSC9218I_GET_FIELD_16(reg, pos) \
+  ((SMSC9218I_GET_FIELD_8(reg, (pos) + 8) << 8) \
+    | SMSC9218I_GET_FIELD_8(reg, pos))
+
+#define SMSC9218I_SWAP(val) \
+  ((((val) >> 24) & 0xff) \
+    | ((((val) >> 16) & 0xff) << 8) \
+    | ((((val) >> 8) & 0xff) << 16) \
+    | (((val) & 0xff) << 24))
+
+/**
+ * @name Receive Status
+ * @{                       
+ */
+
+#define SMSC9218I_RX_STS_FILTER_FAIL SMSC9218I_FLAG(30)
+#define SMSC9218I_RX_STS_GET_LENGTH(reg) (SMSC9218I_GET_FIELD_16(reg, 16) & 0x3fff)
+#define SMSC9218I_RX_STS_ERROR SMSC9218I_FLAG(15)
+#define SMSC9218I_RX_STS_BROADCAST SMSC9218I_FLAG(13)
+#define SMSC9218I_RX_STS_ERROR_LENGTH SMSC9218I_FLAG(12)
+#define SMSC9218I_RX_STS_ERROR_RUNT_FRAME SMSC9218I_FLAG(11)
+#define SMSC9218I_RX_STS_MULTICAST SMSC9218I_FLAG(10)
+#define SMSC9218I_RX_STS_ERROR_TOO_LONG SMSC9218I_FLAG(7)
+#define SMSC9218I_RX_STS_ERROR_COLLISION SMSC9218I_FLAG(6)
+#define SMSC9218I_RX_STS_TYPE SMSC9218I_FLAG(5)
+#define SMSC9218I_RX_STS_WATCHDOG SMSC9218I_FLAG(4)
+#define SMSC9218I_RX_STS_ERROR_MII SMSC9218I_FLAG(3)
+#define SMSC9218I_RX_STS_DRIBBLING_BIT SMSC9218I_FLAG(2)
+#define SMSC9218I_RX_STS_ERROR_CRC SMSC9218I_FLAG(1)
+
+/** @} */
+
+/**
+ * @name Transmit Status
+ * @{                       
+ */
+
+#define SMSC9218I_TX_STS_GET_TAG(reg) SMSC9218I_GET_FIELD_16(reg, 16)
+#define SMSC9218I_TX_STS_ERROR SMSC9218I_FLAG(15)
+#define SMSC9218I_TX_STS_ERROR_LOSS_OF_CARRIER SMSC9218I_FLAG(11)
+#define SMSC9218I_TX_STS_ERROR_NO_CARRIER SMSC9218I_FLAG(10)
+#define SMSC9218I_TX_STS_ERROR_LATE_COLLISION SMSC9218I_FLAG(9)
+#define SMSC9218I_TX_STS_ERROR_EXCESSIVE_COLLISIONS SMSC9218I_FLAG(8)
+#define SMSC9218I_TX_STS_ERROR_EXCESSIVE_DEFERRAL SMSC9218I_FLAG(2)
+#define SMSC9218I_TX_STS_ERROR_DEFERRED SMSC9218I_FLAG(0)
+
+/** @} */
+
+/**
+ * @name Transmit Command A
+ * @{                       
+ */
+
+#define SMSC9218I_TX_A_IOC SMSC9218I_FLAG(31)
+#define SMSC9218I_TX_A_END_ALIGN_4 0
+#define SMSC9218I_TX_A_END_ALIGN_16 SMSC9218I_FLAG(24)
+#define SMSC9218I_TX_A_END_ALIGN_32 SMSC9218I_FLAG(25)
+#define SMSC9218I_TX_A_DOFF(val) SMSC9218I_FIELD_8(val, 16)
+#define SMSC9218I_TX_A_FIRST SMSC9218I_FLAG(13)
+#define SMSC9218I_TX_A_LAST SMSC9218I_FLAG(12)
+#define SMSC9218I_TX_A_FRAGMENT_LENGTH(val) SMSC9218I_FIELD_16(val, 0)
+
+/** @} */
+
+/**
+ * @name Transmit Command B
+ * @{                       
+ */
+
+#define SMSC9218I_TX_B_TAG(val) SMSC9218I_FIELD_16(val, 16)
+#define SMSC9218I_TX_B_GET_TAG(reg) SMSC9218I_GET_FIELD_16(reg, 16)
+#define SMSC9218I_TX_B_DISABLE_CRC SMSC9218I_FLAG(13)
+#define SMSC9218I_TX_B_DISABLE_PAD SMSC9218I_FLAG(12)
+#define SMSC9218I_TX_B_FRAME_LENGTH(val) SMSC9218I_FIELD_16(val, 0)
+
+/** @} */
+
+/**
+ * @name Chip ID and Revision
+ * @{                       
+ */
+
+#define SMSC9218I_ID_REV_GET_ID(reg) SMSC9218I_GET_FIELD_16(reg, 16)
+#define SMSC9218I_ID_REV_GET_REV(reg) SMSC9218I_GET_FIELD_16(reg, 0)
+#define SMSC9218I_ID_REV_ID_CHIP_118 0x0118U
+#define SMSC9218I_ID_REV_ID_CHIP_218 0x118aU
+
+/** @} */
+
+/**
+ * @name Interrupt Configuration
+ * @{                       
+ */
+
+#define SMSC9218I_IRQ_CFG_INT_DEAS(val) SMSC9218I_FIELD_8(val, 24)
+#define SMSC9218I_IRQ_CFG_GET_INT_DEAS(reg) SMSC9218I_GET_FIELD_8(reg, 24)
+#define SMSC9218I_IRQ_CFG_INT_DEAS_CLR SMSC9218I_FLAG(14)
+#define SMSC9218I_IRQ_CFG_INT_DEAS_STS SMSC9218I_FLAG(13)
+#define SMSC9218I_IRQ_CFG_IRQ_INT SMSC9218I_FLAG(12)
+#define SMSC9218I_IRQ_CFG_IRQ_EN SMSC9218I_FLAG(8)
+#define SMSC9218I_IRQ_CFG_IRQ_POL SMSC9218I_FLAG(4)
+#define SMSC9218I_IRQ_CFG_IRQ_TYPE SMSC9218I_FLAG(0)
+
+/** @} */
+
+/**
+ * @name Interrupt Status
+ * @{                       
+ */
+
+#define SMSC9218I_INT_STS_SW SMSC9218I_FLAG(31)
+#define SMSC9218I_INT_STS_TXSTOP SMSC9218I_FLAG(25)
+#define SMSC9218I_INT_STS_RXSTOP SMSC9218I_FLAG(24)
+#define SMSC9218I_INT_STS_RXDFH SMSC9218I_FLAG(23)
+#define SMSC9218I_INT_STS_TIOC SMSC9218I_FLAG(21)
+#define SMSC9218I_INT_STS_RXD SMSC9218I_FLAG(20)
+#define SMSC9218I_INT_STS_GPT SMSC9218I_FLAG(19)
+#define SMSC9218I_INT_STS_PHY SMSC9218I_FLAG(18)
+#define SMSC9218I_INT_STS_PME SMSC9218I_FLAG(17)
+#define SMSC9218I_INT_STS_TXSO SMSC9218I_FLAG(16)
+#define SMSC9218I_INT_STS_RWT SMSC9218I_FLAG(15)
+#define SMSC9218I_INT_STS_RXE SMSC9218I_FLAG(14)
+#define SMSC9218I_INT_STS_TXE SMSC9218I_FLAG(13)
+#define SMSC9218I_INT_STS_TDFO SMSC9218I_FLAG(10)
+#define SMSC9218I_INT_STS_TDFA SMSC9218I_FLAG(9)
+#define SMSC9218I_INT_STS_TSFF SMSC9218I_FLAG(8)
+#define SMSC9218I_INT_STS_TSFL SMSC9218I_FLAG(7)
+#define SMSC9218I_INT_STS_RSFF SMSC9218I_FLAG(4)
+#define SMSC9218I_INT_STS_RSFL SMSC9218I_FLAG(3)
+#define SMSC9218I_INT_STS_GPIO2 SMSC9218I_FLAG(2)
+#define SMSC9218I_INT_STS_GPIO1 SMSC9218I_FLAG(1)
+#define SMSC9218I_INT_STS_GPIO0 SMSC9218I_FLAG(0)
+
+/** @} */
+
+/**
+ * @name Interrupt Enable
+ * @{                       
+ */
+
+#define SMSC9218I_INT_EN_SW SMSC9218I_FLAG(31)
+#define SMSC9218I_INT_EN_TXSTOP SMSC9218I_FLAG(25)
+#define SMSC9218I_INT_EN_RXSTOP SMSC9218I_FLAG(24)
+#define SMSC9218I_INT_EN_RXDFH SMSC9218I_FLAG(23)
+#define SMSC9218I_INT_EN_TIOC SMSC9218I_FLAG(21)
+#define SMSC9218I_INT_EN_RXD SMSC9218I_FLAG(20)
+#define SMSC9218I_INT_EN_GPT SMSC9218I_FLAG(19)
+#define SMSC9218I_INT_EN_PHY SMSC9218I_FLAG(18)
+#define SMSC9218I_INT_EN_PME SMSC9218I_FLAG(17)
+#define SMSC9218I_INT_EN_TXSO SMSC9218I_FLAG(16)
+#define SMSC9218I_INT_EN_RWT SMSC9218I_FLAG(15)
+#define SMSC9218I_INT_EN_RXE SMSC9218I_FLAG(14)
+#define SMSC9218I_INT_EN_TXE SMSC9218I_FLAG(13)
+#define SMSC9218I_INT_EN_TDFO SMSC9218I_FLAG(10)
+#define SMSC9218I_INT_EN_TDFA SMSC9218I_FLAG(9)
+#define SMSC9218I_INT_EN_TSFF SMSC9218I_FLAG(8)
+#define SMSC9218I_INT_EN_TSFL SMSC9218I_FLAG(7)
+#define SMSC9218I_INT_EN_RSFF SMSC9218I_FLAG(4)
+#define SMSC9218I_INT_EN_RSFL SMSC9218I_FLAG(3)
+#define SMSC9218I_INT_EN_GPIO2 SMSC9218I_FLAG(2)
+#define SMSC9218I_INT_EN_GPIO1 SMSC9218I_FLAG(1)
+#define SMSC9218I_INT_EN_GPIO0 SMSC9218I_FLAG(0)
+
+/** @} */
+
+/**
+ * @name Byte Order Testing
+ * @{                       
+ */
+
+#define SMSC9218I_BYTE_TEST SMSC9218I_SWAP(0x87654321U)
+
+/** @} */
+
+/**
+ * @name FIFO Level Interrupts
+ * @{                       
+ */
+
+#define SMSC9218I_FIFO_INT_TDAL(val) SMSC9218I_FIELD_8(val, 24)
+#define SMSC9218I_FIFO_INT_GET_TDAL(reg) SMSC9218I_GET_FIELD_8(reg, 24)
+#define SMSC9218I_FIFO_INT_TSL(val) SMSC9218I_FIELD_8(val, 16)
+#define SMSC9218I_FIFO_INT_GET_TSL(reg) SMSC9218I_GET_FIELD_8(reg, 16)
+#define SMSC9218I_FIFO_INT_RSL(val) SMSC9218I_FIELD_8(val, 0)
+#define SMSC9218I_FIFO_INT_GET_RSL(reg) SMSC9218I_GET_FIELD_8(reg, 0)
+
+/** @} */
+
+/**
+ * @name Receive Configuration
+ * @{                       
+ */
+
+#define SMSC9218I_RX_CFG_END_ALIGN_4 0
+#define SMSC9218I_RX_CFG_END_ALIGN_16 SMSC9218I_FLAG(30)
+#define SMSC9218I_RX_CFG_END_ALIGN_32 SMSC9218I_FLAG(31)
+#define SMSC9218I_RX_CFG_DMA_CNT(val) SMSC9218I_FIELD_8(val, 24)
+#define SMSC9218I_RX_CFG_GET_DMA_CNT(reg) SMSC9218I_GET_FIELD_8(reg, 24)
+#define SMSC9218I_RX_CFG_DUMP SMSC9218I_FLAG(15)
+#define SMSC9218I_RX_CFG_DOFF(val) SMSC9218I_FIELD_8(val, 8)
+#define SMSC9218I_RX_CFG_GET_DOFF(reg) SMSC9218I_GET_FIELD_8(reg, 8)
+
+/** @} */
+
+/**
+ * @name Transmit Configuration
+ * @{                       
+ */
+
+#define SMSC9218I_TX_CFG_SDUMP SMSC9218I_FLAG(15)
+#define SMSC9218I_TX_CFG_DDUMP SMSC9218I_FLAG(14)
+#define SMSC9218I_TX_CFG_SAO SMSC9218I_FLAG(2)
+#define SMSC9218I_TX_CFG_ON SMSC9218I_FLAG(1)
+#define SMSC9218I_TX_CFG_STOP SMSC9218I_FLAG(0)
+
+/** @} */
+
+/**
+ * @name Hardware Configuration
+ * @{                       
+ */
+
+#define SMSC9218I_HW_CFG_AMDIX SMSC9218I_FLAG(24)
+#define SMSC9218I_HW_CFG_MBO SMSC9218I_FLAG(20)
+#define SMSC9218I_HW_CFG_TX_FIF_SZ(val) SMSC9218I_FIELD_8(val, 16)
+#define SMSC9218I_HW_CFG_GET_TX_FIF_SZ(reg) SMSC9218I_GET_FIELD_8(reg, 16)
+#define SMSC9218I_HW_CFG_BITMD_32 SMSC9218I_FLAG(2)
+#define SMSC9218I_HW_CFG_SRST_TO SMSC9218I_FLAG(1)
+#define SMSC9218I_HW_CFG_SRST SMSC9218I_FLAG(0)
+
+/** @} */
+
+/**
+ * @name Receive Datapath Control
+ * @{                       
+ */
+
+#define SMSC9218I_RX_DP_CTRL_FFWD SMSC9218I_FLAG(31)
+
+/** @} */
+
+/**
+ * @name Receive FIFO Information
+ * @{                       
+ */
+
+#define SMSC9218I_RX_FIFO_INF_GET_SUSED(reg) SMSC9218I_GET_FIELD_8(reg, 16)
+#define SMSC9218I_RX_FIFO_INF_GET_DUSED(reg) SMSC9218I_GET_FIELD_16(reg, 0)
+
+/** @} */
+
+/**
+ * @name Transmit FIFO Information
+ * @{                       
+ */
+
+#define SMSC9218I_TX_FIFO_INF_GET_SUSED(reg) SMSC9218I_GET_FIELD_8(reg, 16)
+#define SMSC9218I_TX_FIFO_INF_GET_FREE(reg) SMSC9218I_GET_FIELD_16(reg, 0)
+
+/** @} */
+
+/**
+ * @name Power Management Control
+ * @{                       
+ */
+
+#define SMSC9218I_PMT_CTRL_PM_MODE_D0 0
+#define SMSC9218I_PMT_CTRL_PM_MODE_D1 SMSC9218I_FLAG(12)
+#define SMSC9218I_PMT_CTRL_PM_MODE_D2 SMSC9218I_FLAG(13)
+#define SMSC9218I_PMT_CTRL_PHY_RST SMSC9218I_FLAG(10)
+#define SMSC9218I_PMT_CTRL_WOL_EN SMSC9218I_FLAG(9)
+#define SMSC9218I_PMT_CTRL_ED_EN SMSC9218I_FLAG(8)
+#define SMSC9218I_PMT_CTRL_PME_TYPE_PUPU SMSC9218I_FLAG(6)
+#define SMSC9218I_PMT_CTRL_WUPS_NO 0
+#define SMSC9218I_PMT_CTRL_WUPS_ENERGY SMSC9218I_FLAG(4)
+#define SMSC9218I_PMT_CTRL_WUPS_MAGIC SMSC9218I_FLAG(5)
+#define SMSC9218I_PMT_CTRL_PME_IND SMSC9218I_FLAG(3)
+#define SMSC9218I_PMT_CTRL_PME_POL SMSC9218I_FLAG(2)
+#define SMSC9218I_PMT_CTRL_PME_EN SMSC9218I_FLAG(1)
+#define SMSC9218I_PMT_CTRL_READY SMSC9218I_FLAG(0)
+
+/** @} */
+
+/**
+ * @name General Purpose IO Configuration
+ * @{                       
+ */
+
+#define SMSC9218I_GPIO_CFG_LED3 SMSC9218I_FLAG(30)
+#define SMSC9218I_GPIO_CFG_LED2 SMSC9218I_FLAG(29)
+#define SMSC9218I_GPIO_CFG_LED1 SMSC9218I_FLAG(28)
+#define SMSC9218I_GPIO_CFG_GPIO2_INT_POL SMSC9218I_FLAG(26)
+#define SMSC9218I_GPIO_CFG_GPIO1_INT_POL SMSC9218I_FLAG(25)
+#define SMSC9218I_GPIO_CFG_GPIO0_INT_POL SMSC9218I_FLAG(24)
+#define SMSC9218I_GPIO_CFG_GPIOBUF2 SMSC9218I_FLAG(18)
+#define SMSC9218I_GPIO_CFG_GPIOBUF1 SMSC9218I_FLAG(17)
+#define SMSC9218I_GPIO_CFG_GPIOBUF0 SMSC9218I_FLAG(16)
+#define SMSC9218I_GPIO_CFG_GPIODIR2 SMSC9218I_FLAG(10)
+#define SMSC9218I_GPIO_CFG_GPIODIR1 SMSC9218I_FLAG(9)
+#define SMSC9218I_GPIO_CFG_GPIODIR0 SMSC9218I_FLAG(8)
+#define SMSC9218I_GPIO_CFG_GPO4 SMSC9218I_FLAG(4)
+#define SMSC9218I_GPIO_CFG_GPO3 SMSC9218I_FLAG(3)
+#define SMSC9218I_GPIO_CFG_GPIO0 SMSC9218I_FLAG(0)
+#define SMSC9218I_GPIO_CFG_GPIO2 SMSC9218I_FLAG(2)
+#define SMSC9218I_GPIO_CFG_GPIO1 SMSC9218I_FLAG(1)
+
+/** @} */
+
+/**
+ * @name General Purpose Timer Configuration
+ * @{                       
+ */
+
+#define SMSC9218I_GPT_CFG_TIMER_EN SMSC9218I_FLAG(29)
+#define SMSC9218I_GPT_CFG_LOAD(val) SMSC9218I_FIELD_16(val, 0)
+#define SMSC9218I_GPT_CFG_GET_LOAD(reg) SMSC9218I_GET_FIELD_16(reg, 0)
+
+/** @} */
+
+/**
+ * @name General Purpose Timer Count
+ * @{                       
+ */
+
+#define SMSC9218I_GPT_CNT_GET_CNT SMSC9218I_GET_FIELD_16(reg, 0)
+
+/** @} */
+
+/**
+ * @name Word Swap
+ * @{                       
+ */
+
+#define SMSC9218I_ENDIAN_BIG 0xffffffffU
+
+/** @} */
+
+/**
+ * @name Free Run Counter
+ * @{                       
+ */
+
+#define SMSC9218I_FREE_RUN_GET(reg) SMSC9218I_SWAP(reg)
+
+/** @} */
+
+/**
+ * @name Receiver Dropped Frames Counter
+ * @{                       
+ */
+
+#define SMSC9218I_RX_DROP_GET(reg) SMSC9218I_SWAP(reg)
+
+/** @} */
+
+/**
+ * @name MAC Control and Status Synchronizer Command
+ * @{                       
+ */
+
+#define SMSC9218I_MAC_CSR_CMD_BUSY SMSC9218I_FLAG(31)
+#define SMSC9218I_MAC_CSR_CMD_READ SMSC9218I_FLAG(30)
+#define SMSC9218I_MAC_CSR_CMD_ADDR(val) SMSC9218I_FIELD_8(val, 0)
+#define SMSC9218I_MAC_CSR_CMD_GET_ADDR(reg) SMSC9218I_GET_FIELD_8(reg, 0)
+
+/** @} */
+
+/**
+ * @name MAC Control Register
+ * @{                       
+ */
+
+#define SMSC9218I_MAC_CR 0x00000001U
+#define SMSC9218I_MAC_CR_RXALL 0x80000000U
+#define SMSC9218I_MAC_CR_HBDIS 0x10000000U
+#define SMSC9218I_MAC_CR_RCVOWN 0x00800000U
+#define SMSC9218I_MAC_CR_LOOPBK 0x00200000U
+#define SMSC9218I_MAC_CR_FDPX 0x00100000U
+#define SMSC9218I_MAC_CR_MCPAS 0x00080000U
+#define SMSC9218I_MAC_CR_PRMS 0x00040000U
+#define SMSC9218I_MAC_CR_INVFILT 0x00020000U
+#define SMSC9218I_MAC_CR_PASSBAD 0x00010000U
+#define SMSC9218I_MAC_CR_HFILT 0x00008000U
+#define SMSC9218I_MAC_CR_HPFILT 0x00002000U
+#define SMSC9218I_MAC_CR_LCOLL 0x00001000U
+#define SMSC9218I_MAC_CR_BCAST 0x00000800U
+#define SMSC9218I_MAC_CR_DISRTY 0x00000400U
+#define SMSC9218I_MAC_CR_PADSTR 0x00000100U
+#define SMSC9218I_MAC_CR_BOLMT_MASK 0x000000c0U
+#define SMSC9218I_MAC_CR_BOLMT_10 0x00000000U
+#define SMSC9218I_MAC_CR_BOLMT_8 0x00000040U
+#define SMSC9218I_MAC_CR_BOLMT_4 0x00000080U
+#define SMSC9218I_MAC_CR_BOLMT_1 0x000000c0U
+#define SMSC9218I_MAC_CR_DFCHK 0x00000020U
+#define SMSC9218I_MAC_CR_TXEN 0x00000008U
+#define SMSC9218I_MAC_CR_RXEN 0x00000004U
+
+/** @} */
+
+/**
+ * @name MAC Address High
+ * @{                       
+ */
+
+#define SMSC9218I_MAC_ADDRH 0x00000002U
+#define SMSC9218I_MAC_ADDRH_MASK 0x0000ffffU
+
+/** @} */
+
+/**
+ * @name MAC Address Low
+ * @{                       
+ */
+
+#define SMSC9218I_MAC_ADDRL 0x00000003U
+#define SMSC9218I_MAC_ADDRL_MASK 0xffffffffU
+
+/** @} */
+
+/**
+ * @name Multicast Hash Table High
+ * @{                       
+ */
+
+#define SMSC9218I_MAC_HASHH 0x00000004U
+#define SMSC9218I_MAC_HASHH_MASK 0xffffffffU
+
+/** @} */
+
+/**
+ * @name Multicast Hash Table Low
+ * @{                       
+ */
+
+#define SMSC9218I_MAC_HASHL 0x00000005U
+#define SMSC9218I_MAC_HASHL_MASK 0xffffffffU
+
+/** @} */
+
+/**
+ * @name MII Access
+ * @{                       
+ */
+
+#define SMSC9218I_MAC_MII_ACC 0x00000006U
+#define SMSC9218I_MAC_MII_ACC_PHY_DEFAULT (1U << 11)
+#define SMSC9218I_MAC_MII_ACC_WRITE (1U << 1)
+#define SMSC9218I_MAC_MII_ACC_BUSY (1U << 0)
+#define SMSC9218I_MAC_MII_ACC_ADDR(addr) ((addr) << 6)
+
+/** @} */
+
+/**
+ * @name MII Data
+ * @{                       
+ */
+
+#define SMSC9218I_MAC_MII_DATA 0x00000007U
+
+/** @} */
+
+/**
+ * @name Flow Control
+ * @{                       
+ */
+
+#define SMSC9218I_MAC_FLOW 0x00000008U
+#define SMSC9218I_MAC_FLOW_FCPT_MASK 0xffff0000U
+#define SMSC9218I_MAC_FLOW_FCPASS 0x00000004U
+#define SMSC9218I_MAC_FLOW_FCEN 0x00000002U
+#define SMSC9218I_MAC_FLOW_FCBSY 0x00000001U
+
+/** @} */
+
+/**
+ * @name VLAN1 Tag
+ * @{                       
+ */
+
+#define SMSC9218I_MAC_VLAN1 0x00000009U
+
+/** @} */
+
+/**
+ * @name VLAN2 Tag
+ * @{                       
+ */
+
+#define SMSC9218I_MAC_VLAN2 0x0000000aU
+
+/** @} */
+
+/**
+ * @name Wake-up Frame Filter
+ * @{                       
+ */
+
+#define SMSC9218I_MAC_WUFF 0x0000000bU
+
+/** @} */
+
+/**
+ * @name Wake-up Control and Status
+ * @{                       
+ */
+
+#define SMSC9218I_MAC_WUCSR 0x0000000cU
+#define SMSC9218I_MAC_WUCSR_GUE 0x00000200U
+#define SMSC9218I_MAC_WUCSR_WUFR 0x00000040U
+#define SMSC9218I_MAC_WUCSR_MPR 0x00000020U
+#define SMSC9218I_MAC_WUCSR_WUEN 0x00000004U
+#define SMSC9218I_MAC_WUCSR_MPEN 0x00000002U
+
+/** @} */
+
+/**
+ * @name Basic Control
+ * @{                       
+ */
+
+#define SMSC9218I_PHY_BCR 0x00000000U
+#define SMSC9218I_PHY_BCR_RST 0x00008000U
+#define SMSC9218I_PHY_BCR_LOOPBK 0x00004000U
+#define SMSC9218I_PHY_BCR_SS 0x00002000U
+#define SMSC9218I_PHY_BCR_ANE 0x00001000U
+#define SMSC9218I_PHY_BCR_PWRDN 0x00000800U
+#define SMSC9218I_PHY_BCR_RSTAN 0x00000200U
+#define SMSC9218I_PHY_BCR_FDPLX 0x00000100U
+#define SMSC9218I_PHY_BCR_COLLTST 0x00000080U
+
+/** @} */
+
+/**
+ * @name Basic Status
+ * @{                       
+ */
+
+#define SMSC9218I_PHY_BSR 0x00000001U
+#define SMSC9218I_PHY_BSR_100_T4_ABLE 0x00008000U
+#define SMSC9218I_PHY_BSR_100_TX_FDPLX 0x00004000U
+#define SMSC9218I_PHY_BSR_100_TX_HDPLX 0x00002000U
+#define SMSC9218I_PHY_BSR_10_FDPLX 0x00001000U
+#define SMSC9218I_PHY_BSR_10_HDPLX 0x00000800U
+#define SMSC9218I_PHY_BSR_ANC 0x00000020U
+#define SMSC9218I_PHY_BSR_REM_FAULT 0x00000010U
+#define SMSC9218I_PHY_BSR_AN_ABLE 0x00000008U
+#define SMSC9218I_PHY_BSR_LINK_STATUS 0x00000004U
+#define SMSC9218I_PHY_BSR_JAB_DET 0x00000002U
+#define SMSC9218I_PHY_BSR_EXT_CAP 0x00000001U
+
+/** @} */
+
+/**
+ * @name PHY Identifier 1
+ * @{                       
+ */
+
+#define SMSC9218I_PHY_ID1 0x00000002U
+#define SMSC9218I_PHY_ID1_MASK 0x0000ffffU
+#define SMSC9218I_PHY_ID1_LAN9118 0x00000007U
+#define SMSC9218I_PHY_ID1_LAN9218 (PHY_ID1_LAN9118)
+
+/** @} */
+
+/**
+ * @name PHY Identifier 2
+ * @{                       
+ */
+
+#define SMSC9218I_PHY_ID2 0x00000003U
+#define SMSC9218I_PHY_ID2_MASK 0x0000ffffU
+#define SMSC9218I_PHY_ID2_MODEL_MASK 0x000003f0U
+#define SMSC9218I_PHY_ID2_REV_MASK 0x0000000fU
+#define SMSC9218I_PHY_ID2_LAN9118 0x0000c0d1U
+#define SMSC9218I_PHY_ID2_LAN9218 0x0000c0c3U
+
+/** @} */
+
+/**
+ * @name Auto-negotiation Advertisment
+ * @{                       
+ */
+
+#define SMSC9218I_PHY_ANAR 0x00000004U
+#define SMSC9218I_PHY_ANAR_NXTPG_CAP 0x00008000U
+#define SMSC9218I_PHY_ANAR_REM_FAULT 0x00002000U
+#define SMSC9218I_PHY_ANAR_PAUSE_OP_MASK 0x00000c00U
+#define SMSC9218I_PHY_ANAR_PAUSE_OP_NONE 0x00000000U
+#define SMSC9218I_PHY_ANAR_PAUSE_OP_ASLP 0x00000400U
+#define SMSC9218I_PHY_ANAR_PAUSE_OP_SLP 0x00000800U
+#define SMSC9218I_PHY_ANAR_PAUSE_OP_BOTH 0x00000c00U
+#define SMSC9218I_PHY_ANAR_100_T4_ABLE 0x00000200U
+#define SMSC9218I_PHY_ANAR_100_TX_FDPLX 0x00000100U
+#define SMSC9218I_PHY_ANAR_100_TX_ABLE 0x00000080U
+#define SMSC9218I_PHY_ANAR_10_FDPLX 0x00000040U
+#define SMSC9218I_PHY_ANAR_10_ABLE 0x00000020U
+
+/** @} */
+
+/**
+ * @name Auto-negotiation Link Partner Ability
+ * @{                       
+ */
+
+#define SMSC9218I_PHY_ANLPAR 0x00000005U
+#define SMSC9218I_PHY_ANLPAR_NXTPG_CAP 0x00008000U
+#define SMSC9218I_PHY_ANLPAR_ACK 0x00004000U
+#define SMSC9218I_PHY_ANLPAR_REM_FAULT 0x00002000U
+#define SMSC9218I_PHY_ANLPAR_PAUSE_CAP 0x00000400U
+#define SMSC9218I_PHY_ANLPAR_100_T4_ABLE 0x00000200U
+#define SMSC9218I_PHY_ANLPAR_100_TX_FDPLX 0x00000100U
+#define SMSC9218I_PHY_ANLPAR_100_TX_ABLE 0x00000080U
+#define SMSC9218I_PHY_ANLPAR_10_FDPLX 0x00000040U
+#define SMSC9218I_PHY_ANLPAR_10_ABLE 0x00000020U
+
+/** @} */
+
+/**
+ * @name Auto-negotiation Expansion
+ * @{                       
+ */
+
+#define SMSC9218I_PHY_ANEXPR 0x00000006U
+#define SMSC9218I_PHY_ANEXPR_PARDET_FAULT 0x00000010U
+#define SMSC9218I_PHY_ANEXPR_LP_NXTPG_CAP 0x00000008U
+#define SMSC9218I_PHY_ANEXPR_NXTPG_CAP 0x00000004U
+#define SMSC9218I_PHY_ANEXPR_NEWPG_REC 0x00000002U
+#define SMSC9218I_PHY_ANEXPR_LP_AN_ABLE 0x00000001U
+
+/** @} */
+
+/**
+ * @name Mode Control and Status
+ * @{                       
+ */
+
+#define SMSC9218I_PHY_MCSR 0x00000011U
+#define SMSC9218I_PHY_MCSR_EDPWRDOWN 0x00002000U
+#define SMSC9218I_PHY_MCSR_ENERGYON 0x00000002U
+
+/** @} */
+
+/**
+ * @name Special Modes
+ * @{                       
+ */
+
+#define SMSC9218I_PHY_SPMODES 0x00000012U
+
+/** @} */
+
+/**
+ * @name Special Control and Status Indications
+ * @{                       
+ */
+
+#define SMSC9218I_PHY_CSIR 0x0000001bU
+#define SMSC9218I_PHY_CSIR_SQEOFF 0x00000800U
+#define SMSC9218I_PHY_CSIR_FEFIEN 0x00000020U
+#define SMSC9218I_PHY_CSIR_XPOL 0x00000010U
+
+/** @} */
+
+/**
+ * @name Interrupt Source Flag
+ * @{                       
+ */
+
+#define SMSC9218I_PHY_ISR 0x0000001dU
+#define SMSC9218I_PHY_ISR_INT7 0x00000080U
+#define SMSC9218I_PHY_ISR_INT6 0x00000040U
+#define SMSC9218I_PHY_ISR_INT5 0x00000020U
+#define SMSC9218I_PHY_ISR_INT4 0x00000010U
+#define SMSC9218I_PHY_ISR_INT3 0x00000008U
+#define SMSC9218I_PHY_ISR_INT2 0x00000004U
+#define SMSC9218I_PHY_ISR_INT1 0x00000002U
+
+/** @} */
+
+/**
+ * @name Interrupt Mask
+ * @{                       
+ */
+
+#define SMSC9218I_PHY_IMR 0x0000001eU
+#define SMSC9218I_PHY_IMR_INT7 0x00000080U
+#define SMSC9218I_PHY_IMR_INT6 0x00000040U
+#define SMSC9218I_PHY_IMR_INT5 0x00000020U
+#define SMSC9218I_PHY_IMR_INT4 0x00000010U
+#define SMSC9218I_PHY_IMR_INT3 0x00000008U
+#define SMSC9218I_PHY_IMR_INT2 0x00000004U
+#define SMSC9218I_PHY_IMR_INT1 0x00000002U
+
+/** @} */
+
+/**
+ * @name PHY Special Control and Status
+ * @{                       
+ */
+
+#define SMSC9218I_PHY_PHYSCSR 0x0000001fU
+#define SMSC9218I_PHY_PHYSCSR_ANDONE 0x00001000U
+#define SMSC9218I_PHY_PHYSCSR_4B5B_EN 0x00000040U
+#define SMSC9218I_PHY_PHYSCSR_SPEED_MASK 0x0000001cU
+#define SMSC9218I_PHY_PHYSCSR_SPEED_10HD 0x00000004U
+#define SMSC9218I_PHY_PHYSCSR_SPEED_10FD 0x00000014U
+#define SMSC9218I_PHY_PHYSCSR_SPEED_100HD 0x00000008U
+#define SMSC9218I_PHY_PHYSCSR_SPEED_100FD 0x00000018U
+
+/** @} */
Index: c/src/lib/libbsp/powerpc/mpc55xxevb/network/smsc9218i.c
===================================================================
--- c/src/lib/libbsp/powerpc/mpc55xxevb/network/smsc9218i.c	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
+++ c/src/lib/libbsp/powerpc/mpc55xxevb/network/smsc9218i.c	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -0,0 +1,1666 @@
+/**
+ * @file
+ *
+ * @ingroup mpc55xx
+ *
+ * @brief SMSC - LAN9218i
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * rtems@embedded-brains.de
+ *
+ * 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 <mpc55xx/regs.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include <rtems.h>
+#include <rtems/rtems_bsdnet.h>
+#include <rtems/rtems_mii_ioctl.h>
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <mpc55xx/edma.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/utility.h>
+#include <bsp/smsc9218i.h>
+
+#include <rtems/status-checks.h>
+
+#if MCLBYTES != 2048
+  #warning "unexpected MCLBYTES value"
+#endif
+
+#define SMSC9218I_EVENT_TX RTEMS_EVENT_1
+
+#define SMSC9218I_EVENT_TX_START RTEMS_EVENT_2
+
+#define SMSC9218I_EVENT_TX_ERROR RTEMS_EVENT_3
+
+#define SMSC9218I_EVENT_RX RTEMS_EVENT_4
+
+#define SMSC9218I_EVENT_RX_ERROR RTEMS_EVENT_5
+
+#define SMSC9218I_EVENT_PHY RTEMS_EVENT_6
+
+#define SMSC9218I_EVENT_EDMA RTEMS_EVENT_7
+
+#define SMSC9218I_EVENT_EDMA_ERROR RTEMS_EVENT_8
+
+/* Adjust by two bytes for proper IP header alignment */
+#define SMSC9218I_RX_DATA_OFFSET 2
+
+#define SMSC9218I_TX_JOBS 16U
+
+#define SMSC9218I_TX_JOBS_MAX (SMSC9218I_TX_JOBS - 1U)
+
+/* Maximum number of fragments per frame, see manual section 3.11.3.2 */
+#define SMSC9218I_TX_FRAGMENT_MAX 86
+
+#define SMSC9218I_IRQ_CFG_GLOBAL_ENABLE \
+  (SMSC9218I_IRQ_CFG_IRQ_EN | SMSC9218I_IRQ_CFG_IRQ_TYPE)
+
+#define SMSC9218I_IRQ_CFG_GLOBAL_DISABLE SMSC9218I_IRQ_CFG_IRQ_TYPE
+
+#define SMSC9218I_EDMA_RX_CHANNEL 48
+
+#define SMSC9218I_EDMA_RX_TCD_CDF 0x10004
+
+#define SMSC9218I_EDMA_RX_TCD_BMF 0x10003
+
+#define SMSC9218I_EDMA_TX_CHANNEL 49
+
+#define SMSC9218I_EDMA_TX_TCD_BMF_LINK 0x10011
+
+#define SMSC9218I_EDMA_TX_TCD_BMF_INTERRUPT 0x10003
+
+#define SMSC9218I_EDMA_TX_TCD_BMF_CLEAR 0x10000
+
+#ifdef DEBUG
+  #define SMSC9218I_PRINTF(...) printf(__VA_ARGS__)
+  #define SMSC9218I_PRINTK(...) printk(__VA_ARGS__)
+#else
+  #define SMSC9218I_PRINTF(...)
+  #define SMSC9218I_PRINTK(...)
+#endif
+
+typedef enum {
+  SMSC9218I_NOT_INITIALIZED,
+  SMSC9218I_CONFIGURED,
+  SMSC9218I_STARTED,
+  SMSC9218I_RUNNING
+} smsc9218i_state;
+
+typedef struct {
+  struct arpcom arpcom;
+  struct rtems_mdio_info mdio_info;
+  smsc9218i_state state;
+  rtems_id receive_task;
+  rtems_id transmit_task;
+  mpc55xx_edma_channel_entry edma_receive;
+  mpc55xx_edma_channel_entry edma_transmit;
+  unsigned received_frames;
+  unsigned receive_interrupts;
+  unsigned transmitted_frames;
+  unsigned transmit_interrupts;
+  unsigned receive_too_long_errors;
+  unsigned receive_collision_errors;
+  unsigned receive_crc_errors;
+  unsigned receive_edma_errors;
+  unsigned transmit_errors;
+  unsigned transmit_edma_errors;
+} smsc9218i_driver_entry;
+
+typedef struct {
+  uint32_t a;
+  uint32_t b;
+} smsc9218i_transmit_command;
+
+typedef struct {
+  struct tcd_t command_tcd_table [SMSC9218I_TX_JOBS];
+  struct tcd_t data_tcd_table [SMSC9218I_TX_JOBS];
+  smsc9218i_transmit_command command_table [SMSC9218I_TX_JOBS];
+  struct mbuf *fragment_table [SMSC9218I_TX_JOBS];
+  struct mbuf *frame;
+  struct mbuf *next_fragment;
+  unsigned empty_index;
+  unsigned transfer_index;
+  unsigned transfer_last_index;
+  unsigned todo_index;
+  unsigned empty;
+  unsigned transfer;
+  unsigned todo;
+  uint32_t frame_length;
+  uint32_t command_b;
+  uint16_t tag;
+  bool done;
+} smsc9218i_transmit_job_control;
+
+static void smsc9218i_edma_done(
+  mpc55xx_edma_channel_entry *e,
+  uint32_t error_status
+)
+{
+  rtems_event_set event = error_status == 0 ?
+    SMSC9218I_EVENT_EDMA : SMSC9218I_EVENT_EDMA_ERROR;
+
+  SMSC9218I_PRINTK(
+    "edma: id = 0x%08x, error status = 0x%08x\n",
+    e->id,
+    error_status
+  );
+
+  rtems_event_send(e->id, event);
+}
+
+static smsc9218i_driver_entry smsc9218i_driver_data = {
+  .state = SMSC9218I_NOT_INITIALIZED,
+  .receive_task = RTEMS_ID_NONE,
+  .transmit_task = RTEMS_ID_NONE,
+  .edma_receive = {
+    .channel = SMSC9218I_EDMA_RX_CHANNEL,
+    .done = smsc9218i_edma_done,
+    .id = RTEMS_ID_NONE
+  },
+  .edma_transmit = {
+    .channel = SMSC9218I_EDMA_TX_CHANNEL,
+    .done = smsc9218i_edma_done,
+    .id = RTEMS_ID_NONE
+  }
+};
+
+static void smsc9218i_mac_wait(volatile smsc9218i_registers *regs)
+{
+  while (IS_FLAG_SET(regs->mac_csr_cmd, SMSC9218I_MAC_CSR_CMD_BUSY)) {
+    /* Wait */
+  }
+}
+
+static void smsc9218i_mac_write(
+  volatile smsc9218i_registers *regs,
+  uint32_t address,
+  uint32_t data
+)
+{
+  smsc9218i_mac_wait(regs);
+  regs->mac_csr_data = SMSC9218I_SWAP(data);
+  regs->mac_csr_cmd = SMSC9218I_MAC_CSR_CMD_BUSY
+    | SMSC9218I_MAC_CSR_CMD_ADDR(address);
+  smsc9218i_mac_wait(regs);
+}
+
+static uint32_t smsc9218i_mac_read(
+  volatile smsc9218i_registers *regs,
+  uint32_t address
+)
+{
+  uint32_t mac_csr_data = 0;
+
+  smsc9218i_mac_wait(regs);
+  regs->mac_csr_cmd = SMSC9218I_MAC_CSR_CMD_BUSY
+    | SMSC9218I_MAC_CSR_CMD_READ
+    | SMSC9218I_MAC_CSR_CMD_ADDR(address);
+  smsc9218i_mac_wait(regs);
+  mac_csr_data = regs->mac_csr_data;
+
+  return SMSC9218I_SWAP(mac_csr_data);
+}
+
+static void smsc9218i_phy_wait(volatile smsc9218i_registers *regs)
+{
+  uint32_t mac_mii_acc = 0;
+
+  do {
+    mac_mii_acc = smsc9218i_mac_read(regs, SMSC9218I_MAC_MII_ACC);
+  } while (IS_FLAG_SET(mac_mii_acc, SMSC9218I_MAC_MII_ACC_BUSY));
+}
+
+static void smsc9218i_phy_write(
+  volatile smsc9218i_registers *regs,
+  uint32_t address,
+  uint32_t data
+)
+{
+  smsc9218i_phy_wait(regs);
+  smsc9218i_mac_write(regs, SMSC9218I_MAC_MII_DATA, data);
+  smsc9218i_mac_write(
+    regs,
+    SMSC9218I_MAC_MII_ACC,
+    SMSC9218I_MAC_MII_ACC_PHY_DEFAULT
+      | SMSC9218I_MAC_MII_ACC_BUSY
+      | SMSC9218I_MAC_MII_ACC_WRITE
+      | SMSC9218I_MAC_MII_ACC_ADDR(address)
+  );
+  smsc9218i_phy_wait(regs);
+}
+
+static uint32_t smsc9218i_phy_read(
+  volatile smsc9218i_registers *regs,
+  uint32_t address
+)
+{
+  smsc9218i_phy_wait(regs);
+  smsc9218i_mac_write(
+    regs,
+    SMSC9218I_MAC_MII_ACC,
+    SMSC9218I_MAC_MII_ACC_PHY_DEFAULT
+      | SMSC9218I_MAC_MII_ACC_BUSY
+      | SMSC9218I_MAC_MII_ACC_ADDR(address)
+  );
+  smsc9218i_phy_wait(regs);
+  return smsc9218i_mac_read(regs, SMSC9218I_MAC_MII_DATA);
+}
+
+static void smsc9218i_enable_promiscous_mode(
+  volatile smsc9218i_registers *regs,
+  bool enable
+)
+{
+  uint32_t flags = SMSC9218I_MAC_CR_RXALL | SMSC9218I_MAC_CR_PRMS;
+  uint32_t mac_cr = smsc9218i_mac_read(regs, SMSC9218I_MAC_CR);
+
+  if (enable) {
+    mac_cr = SET_FLAGS(mac_cr, flags);
+  } else {
+    mac_cr = CLEAR_FLAGS(mac_cr, flags);
+  }
+
+  smsc9218i_mac_write(regs, SMSC9218I_MAC_CR, mac_cr);
+}
+
+static void smsc9218i_register_dump(volatile smsc9218i_registers *regs)
+{
+  uint32_t reg = 0;
+
+  reg = regs->id_rev;
+  printf(
+    "id_rev: 0x%08" PRIx32 " (ID = 0x%04" PRIx32
+      ", revision = 0x%04" PRIx32 ")\n",
+    SMSC9218I_SWAP(reg),
+    SMSC9218I_ID_REV_GET_ID(reg),
+    SMSC9218I_ID_REV_GET_REV(reg)
+  );
+
+  reg = regs->irq_cfg;
+  printf("irq_cfg: 0x%08" PRIx32 "\n", SMSC9218I_SWAP(reg));
+
+  reg = regs->int_sts;
+  printf("int_sts: 0x%08" PRIx32 "\n", SMSC9218I_SWAP(reg));
+
+  reg = regs->int_en;
+  printf("int_en: 0x%08" PRIx32 "\n", SMSC9218I_SWAP(reg));
+
+  reg = regs->byte_test;
+  printf("byte_test: 0x%08" PRIx32 "\n", SMSC9218I_SWAP(reg));
+
+  reg = regs->fifo_int;
+  printf("fifo_int: 0x%08" PRIx32 "\n", SMSC9218I_SWAP(reg));
+
+  reg = regs->rx_cfg;
+  printf("rx_cfg: 0x%08" PRIx32 "\n", SMSC9218I_SWAP(reg));
+
+  reg = regs->tx_cfg;
+  printf("tx_cfg: 0x%08" PRIx32 "\n", SMSC9218I_SWAP(reg));
+
+  reg = regs->hw_cfg;
+  printf("hw_cfg: 0x%08" PRIx32 "\n", SMSC9218I_SWAP(reg));
+
+  reg = regs->rx_dp_ctl;
+  printf("rx_dp_ctl: 0x%08" PRIx32 "\n", SMSC9218I_SWAP(reg));
+
+  reg = regs->rx_fifo_inf;
+  printf(
+    "rx_fifo_inf: 0x%08" PRIx32 " (status unused = %" PRIu32
+      ", data unused = %" PRIu32 ")\n",
+    SMSC9218I_SWAP(reg),
+    SMSC9218I_RX_FIFO_INF_GET_SUSED(reg),
+    SMSC9218I_RX_FIFO_INF_GET_DUSED(reg)
+  );
+
+  reg = regs->tx_fifo_inf;
+  printf(
+    "tx_fifo_inf: 0x%08" PRIx32 " (status unused = %" PRIu32
+      ", free = %" PRIu32 ")\n",
+    SMSC9218I_SWAP(reg),
+    SMSC9218I_TX_FIFO_INF_GET_SUSED(reg),
+    SMSC9218I_TX_FIFO_INF_GET_FREE(reg)
+  );
+
+  reg = regs->pmt_ctrl;
+  printf("pmt_ctrl: 0x%08" PRIx32 "\n", SMSC9218I_SWAP(reg));
+
+  reg = regs->gpio_cfg;
+  printf("gpio_cfg: 0x%08" PRIx32 "\n", SMSC9218I_SWAP(reg));
+
+  reg = regs->gpt_cfg;
+  printf("gpt_cfg: 0x%08" PRIx32 "\n", SMSC9218I_SWAP(reg));
+
+  reg = regs->gpt_cnt;
+  printf("gpt_cnt: 0x%08" PRIx32 "\n", SMSC9218I_SWAP(reg));
+
+  reg = regs->word_swap;
+  printf("word_swap: 0x%08" PRIx32 "\n", SMSC9218I_SWAP(reg));
+
+  reg = regs->free_run;
+  printf("free_run: 0x%08" PRIx32 "\n", SMSC9218I_SWAP(reg));
+
+  reg = regs->rx_drop;
+  printf("rx_drop: 0x%08" PRIx32 "\n", SMSC9218I_SWAP(reg));
+
+  reg = regs->afc_cfg;
+  printf("afc_cfg: 0x%08" PRIx32 "\n", SMSC9218I_SWAP(reg));
+
+  printf("mac: cr: 0x%08" PRIx32 "\n", smsc9218i_mac_read(regs, SMSC9218I_MAC_CR));
+  printf("mac: addrh: 0x%08" PRIx32 "\n", smsc9218i_mac_read(regs, SMSC9218I_MAC_ADDRH));
+  printf("mac: addrl: 0x%08" PRIx32 "\n", smsc9218i_mac_read(regs, SMSC9218I_MAC_ADDRL));
+  printf("mac: hashh: 0x%08" PRIx32 "\n", smsc9218i_mac_read(regs, SMSC9218I_MAC_HASHH));
+  printf("mac: hashl: 0x%08" PRIx32 "\n", smsc9218i_mac_read(regs, SMSC9218I_MAC_HASHL));
+  printf("mac: mii_acc: 0x%08" PRIx32 "\n", smsc9218i_mac_read(regs, SMSC9218I_MAC_MII_ACC));
+  printf("mac: mii_data: 0x%08" PRIx32 "\n", smsc9218i_mac_read(regs, SMSC9218I_MAC_MII_DATA));
+  printf("mac: flow: 0x%08" PRIx32 "\n", smsc9218i_mac_read(regs, SMSC9218I_MAC_FLOW));
+  printf("mac: vlan1: 0x%08" PRIx32 "\n", smsc9218i_mac_read(regs, SMSC9218I_MAC_VLAN1));
+  printf("mac: vlan2: 0x%08" PRIx32 "\n", smsc9218i_mac_read(regs, SMSC9218I_MAC_VLAN2));
+  printf("mac: wuff: 0x%08" PRIx32 "\n", smsc9218i_mac_read(regs, SMSC9218I_MAC_WUFF));
+  printf("mac: wucsr: 0x%08" PRIx32 "\n", smsc9218i_mac_read(regs, SMSC9218I_MAC_WUCSR));
+
+  printf("phy: bcr: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_BCR));
+  printf("phy: bsr: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_BSR));
+  printf("phy: id1: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_ID1));
+  printf("phy: id2: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_ID2));
+  printf("phy: anar: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_ANAR));
+  printf("phy: anlpar: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_ANLPAR));
+  printf("phy: anexpr: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_ANEXPR));
+  printf("phy: mcsr: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_MCSR));
+  printf("phy: spmodes: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_SPMODES));
+  printf("phy: cisr: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_CSIR));
+  printf("phy: isr: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_ISR));
+  printf("phy: imr: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_IMR));
+  printf("phy: physcsr: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_PHYSCSR));
+}
+
+static void smsc9218i_interrupt_handler(
+  rtems_vector_number vector,
+  void *arg
+)
+{
+  smsc9218i_driver_entry *e = (smsc9218i_driver_entry *) arg;
+  volatile smsc9218i_registers *const regs = smsc9218i;
+  rtems_event_set re = 0;
+  rtems_event_set te = 0;
+  uint32_t int_en = regs->int_en;
+  uint32_t int_sts = regs->int_sts & int_en;
+  #ifdef DEBUG
+    uint32_t irq_cfg = regs->irq_cfg;
+  #endif
+
+  /* Get interrupt status */
+  SMSC9218I_PRINTK(
+    "interrupt: irq_cfg = 0x%08x, int_sts = 0x%08x, int_en = 0x%08x\n",
+    SMSC9218I_SWAP(irq_cfg),
+    SMSC9218I_SWAP(int_sts),
+    SMSC9218I_SWAP(int_en)
+  );
+
+  /* Disable module interrupts */
+  regs->irq_cfg = SMSC9218I_IRQ_CFG_GLOBAL_DISABLE;
+
+  /* Clear external interrupt status */
+  SIU.EISR.R = 1;
+
+  /* Clear interrupts */
+  regs->int_sts = int_sts;
+
+  /* Check receive interrupts */
+  if (IS_FLAG_SET(int_sts, SMSC9218I_INT_STS_RSFL)) {
+    int_en = CLEAR_FLAG(int_en, SMSC9218I_INT_EN_RSFL);
+    re = SMSC9218I_EVENT_RX;
+  }
+
+  /* Check PHY interrupts */
+  if (IS_FLAG_SET(int_sts, SMSC9218I_INT_STS_PHY)) {
+    int_en = CLEAR_FLAG(int_en, SMSC9218I_INT_EN_PHY);
+    re = SET_FLAG(re, SMSC9218I_EVENT_PHY);
+  }
+
+  /* Send events to receive task */
+  if (re != 0) {
+    SMSC9218I_PRINTK("interrupt: receive: 0x%08x\n", re);
+    ++e->receive_interrupts;
+    (void) rtems_event_send(e->receive_task, re);
+  }
+
+  /* Check transmit interrupts */
+  if (IS_FLAG_SET(int_sts, SMSC9218I_INT_STS_TDFA)) {
+    int_en = CLEAR_FLAG(int_en, SMSC9218I_INT_EN_TDFA);
+    te = SMSC9218I_EVENT_TX;
+  }
+
+  /* Send events to transmit task */
+  if (te != 0) {
+    SMSC9218I_PRINTK("interrupt: transmit: 0x%08x\n", te);
+    ++e->transmit_interrupts;
+    (void) rtems_event_send(e->transmit_task, te);
+  }
+
+  /* Update interrupt enable */
+  regs->int_en = int_en;
+
+  /* Enable module interrupts */
+  regs->irq_cfg = SMSC9218I_IRQ_CFG_GLOBAL_ENABLE;
+}
+
+static void smsc9218i_enable_receive_interrupts(
+  volatile smsc9218i_registers *regs
+)
+{
+  rtems_interrupt_level level;
+
+  rtems_interrupt_disable(level);
+  regs->int_en = SET_FLAG(regs->int_en, SMSC9218I_INT_EN_RSFL);
+  rtems_interrupt_enable(level);
+}
+
+static void smsc9218i_enable_transmit_interrupts(
+  volatile smsc9218i_registers *regs
+)
+{
+  rtems_interrupt_level level;
+
+  rtems_interrupt_disable(level);
+  regs->int_en = SET_FLAG(regs->int_en, SMSC9218I_INT_EN_TDFA);
+  rtems_interrupt_enable(level);
+}
+
+static void smsc9218i_enable_phy_interrupts(
+  volatile smsc9218i_registers *regs
+)
+{
+  rtems_interrupt_level level;
+
+  rtems_interrupt_disable(level);
+  regs->int_en = SET_FLAG(regs->int_en, SMSC9218I_INT_EN_PHY);
+  rtems_interrupt_enable(level);
+}
+
+static struct mbuf *smsc9218i_new_mbuf(struct ifnet *ifp, bool wait)
+{
+  struct mbuf *m = NULL;
+  int mw = wait ? M_WAIT : M_DONTWAIT;
+
+  MGETHDR(m, mw, MT_DATA);
+  if (m != NULL) {
+    MCLGET(m, mw);
+    if (IS_FLAG_SET(m->m_flags, M_EXT)) {
+      /* Set receive interface */
+      m->m_pkthdr.rcvif = ifp;
+
+      return m;
+    } else {
+      m_freem(m);
+    }
+  }
+
+  return NULL;
+}
+
+static void smsc9218i_receive_task(void *arg)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_event_set events = 0;
+  smsc9218i_driver_entry *e = (smsc9218i_driver_entry *) arg;
+  struct ifnet *ifp = &e->arpcom.ac_if;
+  volatile smsc9218i_registers *const regs = smsc9218i;
+  volatile struct tcd_t *tcd = &EDMA.TCD [e->edma_receive.channel];
+  struct tcd_t tcd_init = EDMA_TCD_DEFAULT;
+  uint32_t mac_cr = 0;
+
+  SMSC9218I_PRINTF("%s\n", __func__);
+
+  /* Obtain receive eDMA channel */
+  e->edma_receive.id = e->receive_task;
+  sc = mpc55xx_edma_obtain_channel(&e->edma_receive);
+  RTEMS_CLEANUP_SC(sc, cleanup, "obtain receive eDMA channel");
+
+  /* Setup receive eDMA channel */
+  tcd_init.SDF.B.SSIZE = 2;
+  tcd_init.SDF.B.DSIZE = 2;
+  tcd_init.SADDR = (uint32_t) &regs->rx_fifo_data;
+  *tcd = tcd_init;
+
+  /* Configure receiver */
+  regs->rx_cfg = SMSC9218I_RX_CFG_END_ALIGN_4
+    | SMSC9218I_RX_CFG_DOFF(SMSC9218I_RX_DATA_OFFSET);
+
+  /* Enable MAC receiver */
+  mac_cr = smsc9218i_mac_read(regs, SMSC9218I_MAC_CR) | SMSC9218I_MAC_CR_RXEN;
+  smsc9218i_mac_write(regs, SMSC9218I_MAC_CR, mac_cr);
+
+  /* Enable receive interrupts */
+  smsc9218i_enable_receive_interrupts(regs);
+
+  /* Enable PHY interrupts */
+  smsc9218i_phy_write(
+    regs,
+    SMSC9218I_PHY_IMR,
+    SMSC9218I_PHY_IMR_INT4 | SMSC9218I_PHY_IMR_INT6
+  );
+  smsc9218i_enable_phy_interrupts(regs);
+
+  SMSC9218I_PRINTF(
+    "rx: phy_isr = 0x%08" PRIx32 ", phy_imr = 0x%08" PRIx32 "\n",
+    smsc9218i_phy_read(regs, SMSC9218I_PHY_ISR),
+    smsc9218i_phy_read(regs, SMSC9218I_PHY_IMR)
+  );
+
+  /* Main event loop */
+  while (true) {
+    uint32_t rx_fifo_inf = 0;
+    uint32_t status_used = 0;
+
+    /* Wait for events */
+    sc = rtems_bsdnet_event_receive(
+      SMSC9218I_EVENT_RX | SMSC9218I_EVENT_PHY, 
+      RTEMS_EVENT_ANY | RTEMS_WAIT,
+      RTEMS_NO_TIMEOUT,
+      &events
+    );
+    RTEMS_CLEANUP_SC(sc, cleanup, "wait for events");
+
+    if (IS_FLAG_SET(events, SMSC9218I_EVENT_PHY)) {
+      uint32_t phy_isr = smsc9218i_phy_read(regs, SMSC9218I_PHY_ISR);
+
+      /* TODO */
+
+      printf("rx: PHY event: 0x%08" PRIx32 "\n", phy_isr);
+
+      smsc9218i_enable_phy_interrupts(regs);
+    }
+
+    rx_fifo_inf = regs->rx_fifo_inf;
+    status_used = SMSC9218I_RX_FIFO_INF_GET_SUSED(rx_fifo_inf);
+
+    SMSC9218I_PRINTF(
+      "rx: wake up: events = 0x%08" PRIx32 ", status used = %" PRIu32 "\n",
+      events,
+      status_used
+    );
+
+    while (status_used > 0) {
+      uint32_t rx_fifo_status = regs->rx_fifo_status;
+      uint32_t frame_length = SMSC9218I_RX_STS_GET_LENGTH(rx_fifo_status);
+      uint32_t data_length = frame_length + SMSC9218I_RX_DATA_OFFSET;
+      uint32_t data_misalign = data_length % 4;
+
+      /* Align data length on four byte boundary */
+      if (data_misalign > 0) {
+        data_length += 4 - data_misalign;
+      }
+
+      SMSC9218I_PRINTF(
+        "rx: status = 0x%08" PRIx32 ", frame length = %" PRIu32
+          ", data length = %" PRIu32 ", data used = %" PRIu32 "\n",
+        SMSC9218I_SWAP(rx_fifo_status),
+        frame_length,
+        data_length,
+        SMSC9218I_RX_FIFO_INF_GET_DUSED(rx_fifo_inf)
+      );
+
+      if (IS_FLAG_CLEARED(rx_fifo_status, SMSC9218I_RX_STS_ERROR)) {
+        struct mbuf *m = smsc9218i_new_mbuf(ifp, true);
+        struct ether_header *eh = (struct ether_header *)
+          (mtod(m, char *) + SMSC9218I_RX_DATA_OFFSET);
+        int mbuf_length = (int) frame_length - ETHER_HDR_LEN - ETHER_CRC_LEN;
+        char *data = mtod(m, char *);
+
+        /* Update mbuf */
+        m->m_len = mbuf_length;
+        m->m_pkthdr.len = mbuf_length;
+        m->m_data = data + ETHER_HDR_LEN + SMSC9218I_RX_DATA_OFFSET;
+
+        /* Invalidate data cache */
+        rtems_cache_invalidate_multiple_data_lines(data, data_length);
+
+        /* Start eDMA transfer */
+        tcd->DADDR = (uint32_t) data;
+        tcd->NBYTES = data_length;
+        tcd->CDF.R = SMSC9218I_EDMA_RX_TCD_CDF;
+        tcd->BMF.R = SMSC9218I_EDMA_RX_TCD_BMF;
+
+        /* Wait for eDMA events */
+        sc = rtems_bsdnet_event_receive(
+          SMSC9218I_EVENT_EDMA | SMSC9218I_EVENT_EDMA_ERROR, 
+          RTEMS_EVENT_ANY | RTEMS_WAIT,
+          RTEMS_NO_TIMEOUT,
+          &events
+        );
+        RTEMS_CHECK_SC_TASK(sc, "wait for eDMA events");
+
+        if (IS_FLAG_CLEARED(events, SMSC9218I_EVENT_EDMA_ERROR)) {
+          /* Hand over */
+          ether_input(ifp, eh, m);
+
+          /* Increment received frames counter */
+          ++e->received_frames;
+        } else {
+          /* Increment receive eDMA error counter */
+          ++e->receive_edma_errors;
+        }
+
+        SMSC9218I_PRINTF("rx: eDMA done\n");
+      } else {
+        SMSC9218I_PRINTF("rx: error\n");
+
+        /* Update error counters */
+        if (IS_FLAG_SET(rx_fifo_status, SMSC9218I_RX_STS_ERROR_TOO_LONG)) {
+          ++e->receive_too_long_errors;
+        }
+        if (IS_FLAG_SET(rx_fifo_status, SMSC9218I_RX_STS_ERROR_COLLISION)) {
+          ++e->receive_collision_errors;
+        }
+        if (IS_FLAG_SET(rx_fifo_status, SMSC9218I_RX_STS_ERROR_CRC)) {
+          ++e->receive_crc_errors;
+        }
+
+        /* Discard frame */
+        if (frame_length > 16) {
+          /* Fast forward */
+          regs->rx_dp_ctl = SMSC9218I_RX_DP_CTRL_FFWD;
+
+          while (IS_FLAG_SET(regs->rx_dp_ctl, SMSC9218I_RX_DP_CTRL_FFWD)) {
+            /* Wait */
+          }
+        } else {
+          uint32_t len = data_length / 4;
+          uint32_t i = 0;
+
+          /* Discard data */
+          for (i = 0; i < len; ++i) {
+            regs->rx_fifo_data;
+          }
+        }
+      }
+
+      /* Clear FIFO level status */
+      regs->int_sts = SMSC9218I_INT_STS_RSFL;
+
+      /* Next FIFO status */
+      rx_fifo_inf = regs->rx_fifo_inf;
+      status_used = SMSC9218I_RX_FIFO_INF_GET_SUSED(rx_fifo_inf);
+    }
+
+    SMSC9218I_PRINTF("rx: done\n");
+
+    /* Nothing to do, enable receive interrupts */
+    smsc9218i_enable_receive_interrupts(regs);
+  }
+
+cleanup:
+
+  /* Release network semaphore */
+  rtems_bsdnet_semaphore_release();
+
+  /* Terminate self */
+  (void) rtems_task_delete(RTEMS_SELF);
+}
+
+static void smsc9218i_transmit_job_dump(
+  smsc9218i_transmit_job_control *jc,
+  const char *msg
+)
+{
+  char out [SMSC9218I_TX_JOBS + 1];
+  unsigned c = 0;
+  unsigned s = 0;
+
+  out [SMSC9218I_TX_JOBS] = '\0';
+
+  memset(out, '?', SMSC9218I_TX_JOBS);
+
+  c = jc->todo_index;
+  s = jc->empty;
+  while (s > 0) {
+    out [c] = 'E';
+    --s;
+    if (c < SMSC9218I_TX_JOBS_MAX) {
+      ++c;
+    } else {
+      c = 0;
+    }
+  }
+
+  c = jc->transfer_index;
+  s = jc->todo;
+  while (s > 0) {
+    out [c] = 'T';
+    --s;
+    if (c < SMSC9218I_TX_JOBS_MAX) {
+      ++c;
+    } else {
+      c = 0;
+    }
+  }
+
+  c = jc->empty_index;
+  s = jc->transfer;
+  while (s > 0) {
+    out [c] = 'D';
+    --s;
+    if (c < SMSC9218I_TX_JOBS_MAX) {
+      ++c;
+    } else {
+      c = 0;
+    }
+  }
+
+  printf(
+    "tx: %s: %02u:%02u:%02u %s\n",
+    msg,
+    jc->empty,
+    jc->todo,
+    jc->transfer,
+    out
+  );
+}
+
+static struct mbuf *smsc9218i_next_transmit_fragment(
+  struct ifnet *ifp,
+  smsc9218i_transmit_job_control *jc
+)
+{
+  struct mbuf *m = jc->next_fragment;
+
+  if (m != NULL) {
+    /* Next fragment is from the current frame */
+    jc->next_fragment = m->m_next;
+  } else {
+    /* Dequeue first fragment of the next frame */
+    IF_DEQUEUE(&ifp->if_snd, m);
+
+    /* Update frame head */
+    jc->frame = m;
+
+    if (m != NULL) {
+      struct mbuf *n = m;
+      struct mbuf *p = NULL;
+      uint32_t frame_length = 0;
+      unsigned fragments = 0;
+
+      /* Calculate frame length and fragment number */
+      do {
+        int len = n->m_len;
+
+        if (len > 0) {
+          ++fragments;
+          frame_length += (uint32_t) len;
+
+          if (len < 4) {
+            printf("FIXME\n");
+          }
+
+          /* Next fragment */
+          p = n;
+          n = n->m_next;
+        } else {
+          /* Discard empty fragment and get next */
+          n = m_free(n);
+
+          /* Remove fragment from list */
+          if (p != NULL) {
+            p->m_next = n;
+          } else {
+            jc->frame = n;
+          }
+        }
+      } while (n != NULL);
+
+      if (fragments > SMSC9218I_TX_FRAGMENT_MAX) {
+        printf("FIXME\n");
+      }
+
+      /* Set frame length */
+      jc->frame_length = frame_length;
+
+      /* Update next fragment */
+      jc->next_fragment = jc->frame->m_next;
+
+      /* Update tag */
+      ++jc->tag;
+
+      /* Command B */
+      jc->command_b = SMSC9218I_TX_B_TAG(jc->tag)
+        | SMSC9218I_TX_B_FRAME_LENGTH(jc->frame_length);
+
+      SMSC9218I_PRINTF(
+        "tx: next frame: tag = %u, frame length = %" PRIu32
+          ", fragments = %u\n",
+        (unsigned) jc->tag,
+        frame_length,
+        fragments
+      );
+    } else {
+      /* The transmit queue is empty, we have no next fragment */
+      jc->next_fragment = NULL;
+
+      /* Interface is now inactive */
+      ifp->if_flags = CLEAR_FLAG(ifp->if_flags, IFF_OACTIVE);
+
+      /* Transmit task may wait for events */
+      jc->done = true;
+
+      SMSC9218I_PRINTF("tx: inactive\n");
+    } 
+  }
+
+  return m;
+}
+
+static void smsc9218i_transmit_create_jobs(
+  smsc9218i_transmit_job_control *jc,
+  volatile smsc9218i_registers *const regs,
+  struct ifnet *ifp
+)
+{
+  unsigned n = jc->empty;
+
+  if (n > 0) {
+    unsigned c = jc->todo_index;
+    unsigned i = 0;
+
+    #ifdef DEBUG
+      smsc9218i_transmit_job_dump(jc, "create");
+    #endif
+
+    for (i = 0; i < n; ++i) {
+      struct mbuf *m = smsc9218i_next_transmit_fragment(ifp, jc);
+
+      if (m != NULL) {
+        uint32_t first = m == jc->frame ? SMSC9218I_TX_A_FIRST : 0;
+        uint32_t last = m->m_next == NULL ? SMSC9218I_TX_A_LAST : 0;
+        uint32_t fragment_length = (uint32_t) m->m_len;
+        uint32_t fragment_misalign = (uint32_t) (mtod(m, uintptr_t) % 4);
+        uint32_t data_length = fragment_misalign + fragment_length;
+        uint32_t data_misalign = data_length % 4;
+        uint32_t data = (uint32_t) (mtod(m, char *) - fragment_misalign);
+
+        /* Align data length on four byte boundary */
+        if (data_misalign > 0) {
+          data_length += 4 - data_misalign;
+        }
+
+        /* Cache flush for fragment data */
+        rtems_cache_flush_multiple_data_lines(
+          (const void *) data,
+          data_length
+        );
+
+        asm volatile ( "sync");
+
+        /* Remember fragement */
+        jc->fragment_table [c] = m;
+
+        /* Command A and B */
+        jc->command_table [c].a = SMSC9218I_TX_A_END_ALIGN_4
+          | SMSC9218I_TX_A_DOFF(fragment_misalign)
+          | SMSC9218I_TX_A_FRAGMENT_LENGTH(fragment_length)
+          | first
+          | last;
+        jc->command_table [c].b = jc->command_b;
+
+        /* Data TCD */
+        jc->data_tcd_table [c].SADDR = data;
+        jc->data_tcd_table [c].NBYTES = data_length;
+
+        SMSC9218I_PRINTF("tx: create: index = %u\n", c);
+      } else {
+        /* Nothing to do */
+        break;
+      }
+
+      if (c < SMSC9218I_TX_JOBS_MAX) {
+        ++c;
+      } else {
+        c = 0;
+      }
+    }
+
+    /* Increment jobs to do */
+    jc->todo += i;
+
+    /* Decrement empty count */
+    jc->empty -= i;
+
+    /* Update todo index */
+    jc->todo_index = c;
+
+    #ifdef DEBUG
+      smsc9218i_transmit_job_dump(jc, "create done");
+    #endif
+  } else {
+    /* Transmit task may wait for events */
+    jc->done = true;
+  }
+}
+
+static void smsc9218i_transmit_do_jobs(
+  smsc9218i_transmit_job_control *jc,
+  volatile smsc9218i_registers *const regs,
+  smsc9218i_driver_entry *e
+)
+{
+  if (jc->transfer == 0) {
+    uint32_t tx_fifo_inf = regs->tx_fifo_inf;
+    uint32_t data_free = SMSC9218I_TX_FIFO_INF_GET_FREE(tx_fifo_inf);
+    unsigned c = jc->transfer_index;
+    unsigned last_index = c;
+    unsigned i = 0;
+    unsigned n = jc->todo;
+    struct tcd_t *p = NULL;
+
+    #ifdef DEBUG
+      smsc9218i_transmit_job_dump(jc, "transfer");
+    #endif
+
+    for (i = 0; i < n; ++i) {
+      struct tcd_t *tcd = &jc->data_tcd_table [c];
+      uint32_t data_length = tcd->NBYTES;
+
+      if (data_length <= data_free) {
+        /* Reduce free FIFO space */
+        data_free -= data_length;
+
+        /* Index of last TCD */
+        last_index = c;
+
+        /* Cache flush for previous data TCD */
+        if (p != NULL) {
+          rtems_cache_flush_multiple_data_lines(p, sizeof(*p));
+        }
+      } else {
+        break;
+      }
+
+      p = tcd;
+      if (c < SMSC9218I_TX_JOBS_MAX) {
+        ++c;
+      } else {
+        c = 0;
+      }
+    }
+
+    if (i > 0) {
+      volatile struct tcd_t *channel = &EDMA.TCD [e->edma_transmit.channel];
+      struct tcd_t *start = &jc->command_tcd_table [jc->transfer_index];
+      struct tcd_t *last = &jc->data_tcd_table [last_index];
+
+      /* New transfer index */
+      jc->transfer_index = c;
+
+      /* New last transfer index */
+      jc->transfer_last_index = last_index;
+
+      /* Set jobs in transfer */
+      jc->transfer = i;
+
+      /* Decrement jobs to do */
+      jc->todo -= i;
+
+      /* Cache flush for command table */
+      rtems_cache_flush_multiple_data_lines(
+        jc->command_table,
+        sizeof(jc->command_table)
+      );
+
+      /* Enable interrupt for last data TCD */
+      last->BMF.R = SMSC9218I_EDMA_TX_TCD_BMF_INTERRUPT;
+
+      /* Cache flush for last data TCD */
+      rtems_cache_flush_multiple_data_lines(last, sizeof(*last));
+
+      /* Start eDMA transfer */
+      channel->SADDR = start->SADDR;
+      channel->SDF.R = start->SDF.R;
+      channel->NBYTES = start->NBYTES;
+      channel->SLAST = start->SLAST;
+      channel->DADDR = start->DADDR;
+      channel->CDF.R = start->CDF.R;
+      channel->DLAST_SGA = start->DLAST_SGA;
+      channel->BMF.R = SMSC9218I_EDMA_TX_TCD_BMF_CLEAR;
+      channel->BMF.R = start->BMF.R;
+
+      /* Transmit task may wait for events */
+      jc->done = true;
+    } else if (n > 0) {
+      /* We need to wait until the FIFO has more free space */
+      smsc9218i_enable_transmit_interrupts(regs);
+
+      /* Transmit task may wait for events */
+      jc->done = true;
+    }
+
+    #ifdef DEBUG
+      smsc9218i_transmit_job_dump(jc, "transfer done");
+    #endif
+  }
+}
+
+static void smsc9218i_transmit_finish_jobs(
+  smsc9218i_transmit_job_control *jc,
+  volatile smsc9218i_registers *const regs,
+  smsc9218i_driver_entry *e,
+  rtems_event_set events
+)
+{
+  uint32_t tx_fifo_inf = regs->tx_fifo_inf;
+  uint32_t status_used = SMSC9218I_TX_FIFO_INF_GET_SUSED(tx_fifo_inf);
+  uint32_t s = 0;
+  unsigned n = jc->transfer;
+
+  for (s = 0; s < status_used; ++s) {
+    uint32_t tx_fifo_status = regs->tx_fifo_status;
+
+    if (IS_FLAG_CLEARED(tx_fifo_status, SMSC9218I_TX_STS_ERROR)) {
+      ++e->transmitted_frames;
+    } else {
+      ++e->transmit_errors;
+    }
+
+    SMSC9218I_PRINTF(
+      "tx: transmit status: tag = %" PRIu32 ", status = 0x%08" PRIx32 "\n",
+      SMSC9218I_TX_STS_GET_TAG(tx_fifo_status),
+      SMSC9218I_SWAP(tx_fifo_status)
+    );
+  }
+
+  if (
+    IS_ANY_FLAG_SET(events, SMSC9218I_EVENT_EDMA | SMSC9218I_EVENT_EDMA_ERROR)
+      && n > 0
+  ) {
+    unsigned c = jc->empty_index;
+    unsigned i = 0;
+
+    #ifdef DEBUG
+      smsc9218i_transmit_job_dump(jc, "finish");
+    #endif
+
+    if (IS_FLAG_SET(events, SMSC9218I_EVENT_EDMA_ERROR)) {
+      ++e->transmit_edma_errors;
+    }
+
+    /* Restore last data TCD */
+    jc->data_tcd_table [jc->transfer_last_index].BMF.R =
+      SMSC9218I_EDMA_TX_TCD_BMF_LINK;
+
+    for (i = 0; i < n; ++i) {
+      /* Free fragment buffer */
+      m_free(jc->fragment_table [c]);
+
+      if (c < SMSC9218I_TX_JOBS_MAX) {
+        ++c;
+      } else {
+        c = 0;
+      }
+    }
+
+    /* Increment empty count */
+    jc->empty += n;
+
+    /* New empty index */
+    jc->empty_index = jc->transfer_index;
+
+    /* Clear jobs in transfer */
+    jc->transfer = 0;
+
+    /* Update empty index */
+    jc->empty_index = c;
+
+    #ifdef DEBUG
+      smsc9218i_transmit_job_dump(jc, "finish done");
+    #endif
+  }
+}
+
+/* FIXME */
+static smsc9218i_transmit_job_control smsc_jc  __attribute__ ((aligned (32))) = {
+  .frame = NULL,
+  .next_fragment = NULL,
+  .frame_length = 0,
+  .tag = 0,
+  .command_b = 0,
+  .done = false,
+  .empty_index = 0,
+  .transfer_index = 0,
+  .todo_index = 0,
+  .empty = SMSC9218I_TX_JOBS,
+  .transfer = 0,
+  .todo = 0
+};
+
+static void smsc9218i_transmit_task(void *arg)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_event_set events = 0;
+  smsc9218i_driver_entry *e = (smsc9218i_driver_entry *) arg;
+  struct ifnet *ifp = &e->arpcom.ac_if;
+  volatile smsc9218i_registers *const regs = smsc9218i;
+  uint32_t mac_cr = 0;
+  smsc9218i_transmit_job_control *jc = &smsc_jc;
+  unsigned i = 0;
+
+  SMSC9218I_PRINTF("%s\n", __func__);
+
+  /* Obtain transmit eDMA channel */
+  e->edma_transmit.id = e->transmit_task;
+  sc = mpc55xx_edma_obtain_channel(&e->edma_transmit);
+  RTEMS_CLEANUP_SC(sc, cleanup, "obtain transmit eDMA channel");
+
+  /* Setup transmit eDMA descriptors */
+  for (i = 0; i < SMSC9218I_TX_JOBS; ++i) {
+    unsigned ii = i < SMSC9218I_TX_JOBS_MAX ? i + 1 : 0;
+    struct tcd_t tcd = EDMA_TCD_DEFAULT;
+    struct tcd_t *command_tcd = &jc->command_tcd_table [i];
+    struct tcd_t *data_tcd = &jc->data_tcd_table [i];
+    struct tcd_t *next_command_tcd = &jc->command_tcd_table [ii];
+
+    tcd.SDF.B.SSIZE = 2;
+    tcd.SDF.B.SOFF = 4;
+    tcd.SDF.B.DSIZE = 2;
+    tcd.CDF.B.CITER = 1;
+    tcd.BMF.R = SMSC9218I_EDMA_TX_TCD_BMF_LINK;
+    tcd.DADDR = (uint32_t) &regs->tx_fifo_data;
+
+    tcd.DLAST_SGA = (uint32_t) next_command_tcd;
+    *data_tcd = tcd;
+
+    tcd.SADDR = (uint32_t) &jc->command_table [i].a;
+    tcd.NBYTES = 8;
+    tcd.DLAST_SGA = (uint32_t) data_tcd;
+    *command_tcd = tcd;
+  }
+
+  /*
+   * Cache flush for command TCD.  The content of the command TCD remains
+   * invariant.
+   */
+  rtems_cache_flush_multiple_data_lines(
+    jc->command_tcd_table,
+    sizeof(jc->command_tcd_table)
+  );
+
+  /* Configure transmitter */
+  regs->tx_cfg = SMSC9218I_TX_CFG_SAO | SMSC9218I_TX_CFG_ON;
+
+  /* Enable MAC transmitter */
+  mac_cr = smsc9218i_mac_read(regs, SMSC9218I_MAC_CR) | SMSC9218I_MAC_CR_TXEN;
+  smsc9218i_mac_write(regs, SMSC9218I_MAC_CR, mac_cr);
+
+  /* Main event loop */
+  while (true) {
+    /* Wait for events */
+    sc = rtems_bsdnet_event_receive(
+      SMSC9218I_EVENT_TX
+        | SMSC9218I_EVENT_TX_START
+        | SMSC9218I_EVENT_EDMA
+        | SMSC9218I_EVENT_EDMA_ERROR, 
+      RTEMS_EVENT_ANY | RTEMS_WAIT,
+      RTEMS_NO_TIMEOUT,
+      &events
+    );
+    RTEMS_CLEANUP_SC(sc, cleanup, "wait for events");
+
+    SMSC9218I_PRINTF("tx: wake up: events = 0x%08" PRIx32 "\n", events);
+
+    do {
+      jc->done = false;
+      smsc9218i_transmit_finish_jobs(jc, regs, e, events);
+      smsc9218i_transmit_create_jobs(jc, regs, ifp);
+      smsc9218i_transmit_do_jobs(jc, regs, e);
+    } while (!jc->done);
+
+    SMSC9218I_PRINTF("tx: done\n");
+  }
+
+cleanup:
+
+  /* Release network semaphore */
+  rtems_bsdnet_semaphore_release();
+
+  /* Terminate self */
+  (void) rtems_task_delete(RTEMS_SELF);
+}
+
+static void smsc9218i_test_macros(void)
+{
+  unsigned i = 0;
+  unsigned byte_test = 0x87654321U;
+  unsigned val8 = 0xa5;
+  unsigned val16 = 0xa55a;
+  int r = 0;
+
+  r = SMSC9218I_SWAP(SMSC9218I_BYTE_TEST) == byte_test;
+  printf("[%i] SMSC9218I_SWAP\n", r);
+
+  for (i = 0; i < 32; ++i) {
+    r = SMSC9218I_SWAP(SMSC9218I_FLAG(i)) == (1U << i);
+    printf("[%i] flag: %u\n", r, i);
+  }
+
+  for (i = 0; i < 32; i += 8) {
+    r = SMSC9218I_SWAP(SMSC9218I_FIELD_8(val8, i)) == (val8 << i);
+    printf("[%i] field 8: %u\n", r, i);
+  }
+
+  for (i = 0; i < 32; i += 16) {
+    r = SMSC9218I_SWAP(SMSC9218I_FIELD_16(val16, i)) == (val16 << i);
+    printf("[%i] field 16: %u\n", r, i);
+  }
+
+  for (i = 0; i < 32; i += 8) {
+    r = SMSC9218I_GET_FIELD_8(SMSC9218I_BYTE_TEST, i)
+      == ((byte_test >> i) & 0xffU);
+    printf("[%i] get field 8: %u\n", r, i);
+  }
+
+  for (i = 0; i < 32; i += 16) {
+    r = SMSC9218I_GET_FIELD_16(SMSC9218I_BYTE_TEST, i)
+      == ((byte_test >> i) & 0xffffU);
+    printf("[%i] get field 16: %u\n", r, i);
+  }
+}
+
+static void smsc9218i_set_mac_address(
+  volatile smsc9218i_registers *regs,
+  unsigned char address [6]
+)
+{
+  smsc9218i_mac_write(
+    regs,
+    SMSC9218I_MAC_ADDRL,
+    ((uint32_t) address [3] << 24) | ((uint32_t) address [2] << 16)
+      | ((uint32_t) address [1] << 8) | (uint32_t) address [0]
+  );
+  smsc9218i_mac_write(
+    regs,
+    SMSC9218I_MAC_ADDRH,
+    ((uint32_t) address [5] << 8) | (uint32_t) address [4]
+  );
+}
+
+static void smsc9218i_mac_address_dump(volatile smsc9218i_registers *regs)
+{
+  uint32_t low = smsc9218i_mac_read(regs, SMSC9218I_MAC_ADDRL);
+  uint32_t high = smsc9218i_mac_read(regs, SMSC9218I_MAC_ADDRH);
+
+  printf(
+    "MAC address: %02" PRIx32 ":%02" PRIx32 ":%02" PRIx32
+      ":%02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 "\n",
+    low & 0xff,
+    (low >> 8) & 0xff,
+    (low >> 16) & 0xff,
+    (low >> 24) & 0xff,
+    high & 0xff,
+    (high >> 8) & 0xff
+  );
+}
+
+static void smsc9218i_interrupt_init(
+  smsc9218i_driver_entry *e,
+  volatile smsc9218i_registers *regs
+)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  union SIU_PCR_tag pcr = MPC55XX_ZERO_FLAGS;
+  union SIU_DIRER_tag direr = MPC55XX_ZERO_FLAGS;
+  union SIU_DIRSR_tag dirsr = MPC55XX_ZERO_FLAGS;
+  union SIU_ORER_tag orer = MPC55XX_ZERO_FLAGS;
+  union SIU_IREER_tag ireer = MPC55XX_ZERO_FLAGS;
+  union SIU_IFEER_tag ifeer = MPC55XX_ZERO_FLAGS;
+  union SIU_IDFR_tag idfr = MPC55XX_ZERO_FLAGS;
+  rtems_interrupt_level level;
+
+  /* Configure IRQ input pin */
+  pcr.B.PA = 2;
+  pcr.B.OBE = 0;
+  pcr.B.IBE = 1;
+  pcr.B.DSC = 0;
+  pcr.B.ODE = 0;
+  pcr.B.HYS = 0;
+  pcr.B.SRC = 3;
+  pcr.B.WPE = 0;
+  pcr.B.WPS = 1;
+  SIU.PCR [193].R = pcr.R;
+
+  /* DMA/Interrupt Request Select */
+  rtems_interrupt_disable(level);
+  dirsr.R = SIU.DIRSR.R;
+  dirsr.B.DIRS0 = 0;
+  SIU.DIRSR.R = dirsr.R;
+  rtems_interrupt_enable(level);
+
+  /* Overrun Request Enable */
+  rtems_interrupt_disable(level);
+  orer.R = SIU.ORER.R;
+  orer.B.ORE0 = 0;
+  SIU.ORER.R = orer.R;
+  rtems_interrupt_enable(level);
+
+  /* IRQ Rising-Edge Enable */
+  rtems_interrupt_disable(level);
+  ireer.R = SIU.IREER.R;
+  ireer.B.IREE0 = 0;
+  SIU.IREER.R = ireer.R;
+  rtems_interrupt_enable(level);
+
+  /* IRQ Falling-Edge Enable */
+  rtems_interrupt_disable(level);
+  ifeer.R = SIU.IFEER.R;
+  ifeer.B.IFEE0 = 1;
+  SIU.IFEER.R = ifeer.R;
+  rtems_interrupt_enable(level);
+
+  /* IRQ Digital Filter */
+  rtems_interrupt_disable(level);
+  idfr.R = SIU.IDFR.R;
+  idfr.B.DFL = 0;
+  SIU.IDFR.R = idfr.R;
+  rtems_interrupt_enable(level);
+
+  /* Clear external interrupt status */
+  SIU.EISR.R = 1;
+
+  /* DMA/Interrupt Request Enable */
+  rtems_interrupt_disable(level);
+  direr.R = SIU.DIRER.R;
+  direr.B.EIRE0 = 1;
+  SIU.DIRER.R = direr.R;
+  rtems_interrupt_enable(level);
+
+  /* Install interrupt handler */
+  sc = rtems_interrupt_handler_install(
+    MPC55XX_IRQ_SIU_EXTERNAL_0,
+    "SMSC9218i",
+    RTEMS_INTERRUPT_UNIQUE,
+    smsc9218i_interrupt_handler,
+    e
+  );
+  RTEMS_SYSLOG_ERROR_SC(sc, "install interrupt handler\n");
+
+  /* Enable interrupts and use push-pull driver (active low) */
+  regs->irq_cfg = SMSC9218I_IRQ_CFG_GLOBAL_ENABLE;
+}
+
+static void smsc9218i_reset_signal(bool signal)
+{
+  SIU.GPDO [186].R = signal ? 1 : 0;
+}
+
+static void smsc9218i_reset_signal_init(void)
+{
+  union SIU_PCR_tag pcr = MPC55XX_ZERO_FLAGS;
+
+  smsc9218i_reset_signal(true);
+
+  pcr.B.PA = 0;
+  pcr.B.OBE = 1;
+  pcr.B.IBE = 0;
+  pcr.B.DSC = 0;
+  pcr.B.ODE = 0;
+  pcr.B.HYS = 0;
+  pcr.B.SRC = 3;
+  pcr.B.WPE = 1;
+  pcr.B.WPS = 1;
+
+  SIU.PCR [186].R = pcr.R;
+}
+
+static void smsc9218i_interface_init(void *arg)
+{
+  smsc9218i_driver_entry *e = (smsc9218i_driver_entry *) arg;
+  struct ifnet *ifp = &e->arpcom.ac_if;
+  volatile smsc9218i_registers *const regs = smsc9218i;
+
+  SMSC9218I_PRINTF("%s\n", __func__);
+
+  if (e->state == SMSC9218I_CONFIGURED) {
+    /* Hardware reset */
+    smsc9218i_reset_signal_init();
+    smsc9218i_reset_signal(false);
+    rtems_bsp_delay(200);
+    smsc9218i_reset_signal(true);
+
+    /* Register dump */
+    smsc9218i_register_dump(regs);
+
+    /* Set hardware configuration */
+    regs->hw_cfg = SMSC9218I_HW_CFG_MBO | SMSC9218I_HW_CFG_TX_FIF_SZ(5);
+
+    /* MAC address */
+    smsc9218i_set_mac_address(regs, e->arpcom.ac_enaddr);
+    smsc9218i_mac_address_dump(regs);
+
+    /* Initialize interrupts */
+    smsc9218i_interrupt_init(e, regs);
+
+    /* Set MAC control */
+    smsc9218i_mac_write(regs, SMSC9218I_MAC_CR, SMSC9218I_MAC_CR_FDPX);
+
+    /* Set FIFO interrupts */
+    regs->fifo_int = SMSC9218I_FIFO_INT_TDAL(32);
+
+    /* Start receive task */
+    if (e->receive_task == RTEMS_ID_NONE) {
+      e->receive_task = rtems_bsdnet_newproc(
+        "ntrx", 
+        4096, 
+        smsc9218i_receive_task,
+        e
+      );
+    }
+
+    /* Start transmit task */
+    if (e->transmit_task == RTEMS_ID_NONE) {
+      e->transmit_task = rtems_bsdnet_newproc(
+        "nttx", 
+        4096, 
+        smsc9218i_transmit_task,
+        e
+      );
+    }
+
+    /* Change state */
+    if (e->receive_task != RTEMS_ID_NONE
+      && e->transmit_task != RTEMS_ID_NONE) {
+      e->state = SMSC9218I_STARTED;
+    }
+  }
+
+  if (e->state == SMSC9218I_STARTED) {
+    /* Enable promiscous mode */
+    smsc9218i_enable_promiscous_mode(
+      regs,
+      IS_FLAG_SET(ifp->if_flags, IFF_PROMISC)
+    );
+
+    /* Set interface to running state */
+    ifp->if_flags = SET_FLAG(ifp->if_flags, IFF_RUNNING);
+
+    /* Change state */
+    e->state = SMSC9218I_RUNNING;
+  }
+}
+
+static void smsc9218i_interface_stats(const smsc9218i_driver_entry *e)
+{
+  printf("received frames:          %u\n", e->received_frames);
+  printf("receive interrupts:       %u\n", e->receive_interrupts);
+  printf("transmitted frames:       %u\n", e->transmitted_frames);
+  printf("transmit interrupts:      %u\n", e->transmit_interrupts);
+  printf("receive to long errors:   %u\n", e->receive_too_long_errors);
+  printf("receive collision errors: %u\n", e->receive_collision_errors);
+  printf("receive CRC errors:       %u\n", e->receive_crc_errors);
+  printf("receive eDMA errors:      %u\n", e->receive_edma_errors);
+  printf("transmit errors:          %u\n", e->transmit_errors);
+  printf("transmit eDMA errors:     %u\n", e->transmit_edma_errors);
+}
+
+static int smsc9218i_interface_ioctl(
+  struct ifnet *ifp,
+  ioctl_command_t command,
+  caddr_t data
+) {
+  smsc9218i_driver_entry *e = (smsc9218i_driver_entry *) ifp->if_softc;
+  int rv = 0;
+
+  SMSC9218I_PRINTF("%s\n", __func__);
+
+  switch (command)  {
+    case SIOCGIFMEDIA:
+    case SIOCSIFMEDIA:
+      rtems_mii_ioctl(&e->mdio_info, e, (int) command, (int *) data);
+      break;
+    case SIOCGIFADDR:
+    case SIOCSIFADDR:
+      ether_ioctl(ifp, command, data);
+      break;
+    case SIOCSIFFLAGS:
+      if (ifp->if_flags & IFF_RUNNING) {
+        /* TODO: off */
+      }
+      if (ifp->if_flags & IFF_UP) {
+        ifp->if_flags = SET_FLAG(ifp->if_flags, IFF_RUNNING);
+        /* TODO: init */
+      }
+      break;
+    case SIO_RTEMS_SHOW_STATS:
+      smsc9218i_interface_stats(e);
+      break;
+    default:
+      rv = EINVAL;
+      break;
+  }
+
+  return rv;
+}
+
+static void smsc9218i_interface_start(struct ifnet *ifp)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  smsc9218i_driver_entry *e = (smsc9218i_driver_entry *) ifp->if_softc;
+
+  /* Interface is now active */
+  ifp->if_flags = SET_FLAG(ifp->if_flags, IFF_OACTIVE);
+
+  sc = rtems_event_send(e->transmit_task, SMSC9218I_EVENT_TX_START);
+  RTEMS_SYSLOG_ERROR_SC(sc, "send transmit start event");
+}
+
+static void smsc9218i_interface_watchdog(struct ifnet *ifp)
+{
+  SMSC9218I_PRINTF("%s\n", __func__);
+}
+
+static int smsc9218i_attach(struct rtems_bsdnet_ifconfig *config)
+{
+  smsc9218i_driver_entry *e = &smsc9218i_driver_data;
+  struct ifnet *ifp = &e->arpcom.ac_if;
+  char *unit_name = NULL;
+  int unit_number = rtems_bsdnet_parse_driver_name(config, &unit_name);
+
+  /* Check parameter */
+  if (unit_number < 0) {
+    RTEMS_SYSLOG_ERROR("parse error for interface name\n");
+    return 0;
+  }
+  if (unit_number != 0) {
+    RTEMS_DO_CLEANUP(smsc9218i_attach_cleanup, "unexpected unit number");
+  }
+  if (config->hardware_address == NULL) {
+    RTEMS_DO_CLEANUP(smsc9218i_attach_cleanup, "MAC address missing");
+  }
+  if (e->state != SMSC9218I_NOT_INITIALIZED) {
+    RTEMS_DO_CLEANUP(smsc9218i_attach_cleanup, "already attached");
+  }
+
+  /* Interrupt number */
+  config->irno = MPC55XX_IRQ_SIU_EXTERNAL_0;
+
+  /* Device control */
+  config->drv_ctrl = e;
+
+  /* Receive unit number */
+  config->rbuf_count = 0;
+
+  /* Transmit unit number */
+  config->xbuf_count = 0;
+
+  /* Copy MAC address */
+  memcpy(e->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
+
+  /* Set interface data */
+  ifp->if_softc = e;
+  ifp->if_unit = (short) unit_number;
+  ifp->if_name = unit_name;
+  ifp->if_mtu = config->mtu > 0 ? (u_long) config->mtu : ETHERMTU;
+  ifp->if_init = smsc9218i_interface_init;
+  ifp->if_ioctl = smsc9218i_interface_ioctl;
+  ifp->if_start = smsc9218i_interface_start;
+  ifp->if_output = ether_output;
+  ifp->if_watchdog = smsc9218i_interface_watchdog;
+  ifp->if_flags = config->ignore_broadcast ? 0 : IFF_BROADCAST;
+  ifp->if_snd.ifq_maxlen = ifqmaxlen;
+  ifp->if_timer = 0;
+
+  /* Change status */
+  e->state = SMSC9218I_CONFIGURED;
+
+  /* Attach the interface */
+  if_attach(ifp);
+  ether_ifattach(ifp);
+
+  return 1;
+
+smsc9218i_attach_cleanup:
+
+  /* FIXME: Type */
+  free(unit_name, (int) 0xdeadbeef);
+
+  return 0;
+}
+
+int smsc9218i_attach_detach(
+  struct rtems_bsdnet_ifconfig *config,
+  int attaching
+) {
+  /* FIXME: Return value */
+
+  if (attaching) {
+    return smsc9218i_attach(config);
+  } else {
+    /* TODO */
+    return 0;
+  }
+}
Index: c/src/lib/libbsp/powerpc/mpc55xxevb/preinstall.am
===================================================================
--- c/src/lib/libbsp/powerpc/mpc55xxevb/preinstall.am	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libbsp/powerpc/mpc55xxevb/preinstall.am	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -86,7 +86,19 @@
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-config.h
 
+$(PROJECT_INCLUDE)/bsp/smsc9218i.h: include/smsc9218i.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/smsc9218i.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/smsc9218i.h
+
 $(PROJECT_INCLUDE)/bsp/irq-generic.h: ../../shared/include/irq-generic.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-generic.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-generic.h
+
+$(PROJECT_INCLUDE)/bsp/irq-info.h: ../../shared/include/irq-info.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-info.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-info.h
+
+$(PROJECT_INCLUDE)/bsp/utility.h: ../../shared/include/utility.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/utility.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/utility.h
 
 $(PROJECT_INCLUDE)/bsp/tictac.h: ../shared/include/tictac.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
Index: c/src/lib/libbsp/powerpc/mpc55xxevb/startup/bspstart.c
===================================================================
--- c/src/lib/libbsp/powerpc/mpc55xxevb/startup/bspstart.c	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libbsp/powerpc/mpc55xxevb/startup/bspstart.c	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -93,9 +93,38 @@
 static void mpc55xx_ebi_init()
 {
-	struct EBI_CS_tag cs = { BR : MPC55XX_ZERO_FLAGS, OR : MPC55XX_ZERO_FLAGS };
+	struct EBI_CS_tag cs = { .BR = MPC55XX_ZERO_FLAGS, .OR = MPC55XX_ZERO_FLAGS };
 	union SIU_PCR_tag pcr = MPC55XX_ZERO_FLAGS;
+	struct MMU_tag mmu = MMU_DEFAULT;
 	int i = 0;
 
-	/* External SRAM (0 wait states, 512kB, 4 word burst) */
+	/* ADDR [8 : 31] */
+	for (i = 4; i < 4 + 24; ++i) {
+		SIU.PCR [i].R = 0x440;
+	}
+
+	/* DATA [0 : 15] */
+	for (i = 28; i < 28 + 16; ++i) {
+		SIU.PCR [i].R = 0x440;
+	}
+
+	/* RD_!WR */
+	SIU.PCR [62].R = 0x443;
+
+	/* !BDIP */
+	SIU.PCR [63].R = 0x443;
+
+	/* !WE [0 : 3] */
+	for (i = 64; i < 64 + 4; ++i) {
+		SIU.PCR [i].R = 0x443;
+	}
+
+	/* !OE */
+	SIU.PCR [68].R = 0x443;
+
+	/* !TS */
+	SIU.PCR [69].R = 0x443;
+
+	/* External SRAM (2 wait states, 512kB, 4 word burst) */
+
 	cs.BR.B.BA = 0;
 	cs.BR.B.PS = 1;
@@ -115,30 +144,42 @@
 	SIU.PCR [0].R = 0x443;
 
-	/* ADDR [8 : 31] */
-	for (i = 4; i < 4 + 24; ++i) {
-		SIU.PCR [i].R = 0x440;
-	}
-
-	/* DATA [0 : 15] */
-	for (i = 28; i < 28 + 16; ++i) {
-		SIU.PCR [i].R = 0x440;
-	}
-
-	/* RD_!WR */
-	SIU.PCR [62].R = 0x443;
-
-	/* !BDIP */
-	SIU.PCR [63].R = 0x443;
-
-	/* !WE [0 : 3] */
-	for (i = 64; i < 64 + 4; ++i) {
-		SIU.PCR [i].R = 0x443;
-	}
-
-	/* !OE */
-	SIU.PCR [68].R = 0x443;
-
-	/* !TS */
-	SIU.PCR [69].R = 0x443;
+	/* External Ethernet Controller (3 wait states, 64kB) */
+
+	mmu.MAS0.B.ESEL = 5;
+	mmu.MAS1.B.VALID = 1;
+	mmu.MAS1.B.IPROT = 1;
+	mmu.MAS1.B.TSIZ = 1;
+	mmu.MAS2.B.EPN = 0x3fff8;
+	mmu.MAS2.B.I = 1;
+	mmu.MAS2.B.G = 1;
+	mmu.MAS3.B.RPN = 0x3fff8;
+	mmu.MAS3.B.UW = 1;
+	mmu.MAS3.B.SW = 1;
+	mmu.MAS3.B.UR = 1;
+	mmu.MAS3.B.SR = 1;
+
+	PPC_SET_SPECIAL_PURPOSE_REGISTER( FREESCALE_EIS_MAS0, mmu.MAS0.R);
+	PPC_SET_SPECIAL_PURPOSE_REGISTER( FREESCALE_EIS_MAS1, mmu.MAS1.R);
+	PPC_SET_SPECIAL_PURPOSE_REGISTER( FREESCALE_EIS_MAS2, mmu.MAS2.R);
+	PPC_SET_SPECIAL_PURPOSE_REGISTER( FREESCALE_EIS_MAS3, mmu.MAS3.R);
+
+	asm volatile ("tlbwe");
+
+	cs.BR.B.BA = 0x7fff;
+	cs.BR.B.PS = 1;
+	cs.BR.B.BL = 0;
+	cs.BR.B.WEBS = 0;
+	cs.BR.B.TBDIP = 0;
+	cs.BR.B.BI = 1;
+	cs.BR.B.V = 1;
+
+	cs.OR.B.AM = 0x1ffff;
+	cs.OR.B.SCY = 1;
+	cs.OR.B.BSCY = 0;
+
+	EBI.CS [3] = cs;
+
+	/* !CS [3] */
+	SIU.PCR [3].R = 0x443;
 }
 
@@ -199,5 +240,6 @@
 	}
 	
-	RTEMS_DEBUG_PRINT( "BSP start done\n");
+	/* Initialize eMIOS */
+	mpc55xx_emios_initialize( 1);
 
 	return;
Index: c/src/lib/libbsp/powerpc/mpc55xxevb/startup/sd-card-init.c
===================================================================
--- c/src/lib/libbsp/powerpc/mpc55xxevb/startup/sd-card-init.c	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libbsp/powerpc/mpc55xxevb/startup/sd-card-init.c	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -19,5 +19,5 @@
  */
 
-#include  <stdio.h>
+#include <stdio.h>
 
 #include <mpc55xx/mpc55xx.h>
@@ -25,11 +25,7 @@
 #include <mpc55xx/dspi.h>
 
-#include <libchip/spi-sd-card.h>
-
-#define DEBUG
+#include <bsp.h>
 
 #include <rtems/status-checks.h>
-
-#include <bsp.h>
 
 static rtems_status_code mpc55xx_dspi_init(void)
@@ -89,14 +85,11 @@
 }
 
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <dirent.h>
 #include <stdio.h>
 #include <rtems/fsmount.h>
 #include <rtems/dosfs.h>
-#include <rtems/ide_part_table.h>
+#include <rtems/bdpart.h>
 #include <rtems/console.h>
+
+#include <libchip/spi-sd-card.h>
 
 #define MPC55XX_DEVICE "sd-card-a"
@@ -118,19 +111,8 @@
 };
 
-#define SD_CARD_NUMBER 1
-
-sd_card_driver_entry sd_card_driver_table [SD_CARD_NUMBER] = { {
-#if 0
-		.driver = {
-			.ops = &sd_card_driver_ops,
-			.size = sizeof( sd_card_driver_entry)
-		},
-		.table_index = 0,
-		.minor = 0,
-#endif
-		.device_name = "sd-card-a",
-#if 0
-		.disk_device_name = "/dev/sd-card-a",
-#endif
+sd_card_driver_entry sd_card_driver_table [] = {
+	{
+		.device_name = "/dev/sd-card-a",
+		.bus = 0,
 		.transfer_mode = SD_CARD_TRANSFER_MODE_DEFAULT,
 		.command = SD_CARD_COMMAND_DEFAULT,
@@ -141,11 +123,13 @@
 		.block_size = 0,
 		.block_size_shift = 0,
-		.busy = 1,
-		.verbose = 1,
-		.schedule_if_busy = 0,
+		.busy = true,
+		.verbose = true,
+		.schedule_if_busy = false
 	}
 };
 
-rtems_status_code mpc55xx_sd_card_init(void)
+size_t sd_card_driver_table_size = sizeof( sd_card_driver_table) / sizeof( sd_card_driver_table [0]);
+
+rtems_status_code mpc55xx_sd_card_init( bool mount)
 {
 	rtems_status_code sc = RTEMS_SUCCESSFUL;
@@ -158,15 +142,16 @@
 	RTEMS_CHECK_SC( rv, "Intitalize DSPI bus");
 
-	rv = rtems_libi2c_register_drv( e->device_name, (rtems_libi2c_drv_t *) e, mpc55xx_dspi_bus_table [0].bus_number, 0);
-	RTEMS_CHECK_RV_SC( rv, "Register SD Card driver");
+	e->bus = mpc55xx_dspi_bus_table [0].bus_number;
 
-	sc = rtems_ide_part_table_initialize( MPC55XX_DEVICE_FILE);
-	RTEMS_CHECK_SC( sc, "Initialize IDE partition table");
+	sc = sd_card_register();
+	RTEMS_CHECK_SC( sc, "Register SD Card");
 
-	rv = mkdir( MPC55XX_MOUNT_POINT, S_IRWXU);
-	RTEMS_CHECK_RV_SC( rv, "Create mount point");
+	if (mount) {
+		sc = rtems_bdpart_register_from_disk( MPC55XX_DEVICE_FILE);
+		RTEMS_CHECK_SC( sc, "Initialize IDE partition table");
 
-	rv = rtems_fsmount( mpc55xx_fs_table, sizeof( mpc55xx_fs_table) / sizeof( mpc55xx_fs_table [0]), NULL);
-	RTEMS_CHECK_RV_SC( rv, "Mount file systems");
+		rv = rtems_fsmount( mpc55xx_fs_table, sizeof( mpc55xx_fs_table) / sizeof( mpc55xx_fs_table [0]), NULL);
+		RTEMS_CHECK_RV_SC( rv, "Mount file systems");
+	}
 
 	return RTEMS_SUCCESSFUL;
Index: c/src/lib/libbsp/powerpc/mpc55xxevb/tests/tests.c
===================================================================
--- c/src/lib/libbsp/powerpc/mpc55xxevb/tests/tests.c	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libbsp/powerpc/mpc55xxevb/tests/tests.c	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -37,6 +37,4 @@
 #include <libcpu/powerpc-utility.h>
 
-/* #define DEBUG */
-
 #include <rtems/status-checks.h>
 
@@ -217,5 +215,8 @@
 
 	printk( "Boot time: %u\n", ppc_time_base());
+
+	/*
 	test_mpc55xx_intc( 0);
+	*/
 
 	rv = rtems_libi2c_initialize();
@@ -269,5 +270,5 @@
 		rtems_build_name ( 'P', 'I', 'N', 'G'),
 		1,
-		RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+		RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_PRIORITY,
 		RTEMS_NO_PRIORITY,
 		&test_mpc55xx_dspi_ping
@@ -278,5 +279,5 @@
 		rtems_build_name ( 'P', 'O', 'N', 'G'),
 		0,
-		RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+		RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_PRIORITY,
 		RTEMS_NO_PRIORITY,
 		&test_mpc55xx_dspi_pong
@@ -326,4 +327,6 @@
 	RTEMS_CHECK_SC( sc, "rtems_task_start");
 
+	return RTEMS_SUCCESSFUL;
+
 	rtems_id intc_id;
 	sc = rtems_task_create(
@@ -339,9 +342,8 @@
 	RTEMS_CHECK_SC( sc, "rtems_task_start");
 
-	sc = rtems_task_delete( RTEMS_SELF);
-	RTEMS_CHECK_SC( sc, "rtems_task_delete");
-
 	return RTEMS_SUCCESSFUL;
 }
+
+#if 0
 
 #include <sys/types.h>
@@ -422,33 +424,4 @@
 }
 
-#define SD_CARD_NUMBER 1
-
-static sd_card_driver_entry sd_card_driver_table_XXX [SD_CARD_NUMBER] = { {
-#if 0
-		driver : {
-			ops : &sd_card_driver_ops,
-			size : sizeof( sd_card_driver_entry)
-		},
-		table_index : 0,
-		minor : 0,
-#endif
-		device_name : "sd-card-a",
-#if 0
-		disk_device_name : "/dev/sd-card-a",
-#endif
-		transfer_mode : SD_CARD_TRANSFER_MODE_DEFAULT,
-		command : SD_CARD_COMMAND_DEFAULT,
-		/* response : whatever, */
-		response_index : SD_CARD_COMMAND_SIZE,
-		n_ac_max : SD_CARD_N_AC_MAX_DEFAULT,
-		block_number : 0,
-		block_size : 0,
-		block_size_shift : 0,
-		busy : 1,
-		verbose : 1,
-		schedule_if_busy : 0,
-	}
-};
-
 rtems_task test_sd_card( rtems_task_argument arg)
 {
@@ -485,15 +458,17 @@
 	RTEMS_CHECK_SC_TASK( sc, "Initialize IDE partition table");
 
+	rv = mkdir( TEST_SD_CARD_MOUNT_POINT, S_IRWXU);
+	RTEMS_CHECK_RV_TASK( rv, "Create mount point");
+
+	rv = rtems_fsmount( test_sd_card_fs_table, sizeof( test_sd_card_fs_table) / sizeof( test_sd_card_fs_table [0]), NULL);
+	RTEMS_CHECK_RV_TASK( rv, "Mount file systems");
+
 	rv = test_sd_card_print_dir( "/dev", 0);
 	RTEMS_CHECK_RV_TASK( rv, "Print directory");
 
-	rv = mkdir( TEST_SD_CARD_MOUNT_POINT, S_IRWXU);
-	RTEMS_CHECK_RV_TASK( rv, "Create mount point");
-
-	rv = rtems_fsmount( test_sd_card_fs_table, sizeof( test_sd_card_fs_table) / sizeof( test_sd_card_fs_table [0]), NULL);
-	RTEMS_CHECK_RV_TASK( rv, "Mount file systems");
-
-	/*rv = test_sd_card_print_dir( TEST_SD_CARD_MOUNT_POINT, 0); */
-	/*RTEMS_CHECK_RV_TASK( rv, "Print directory"); */
+	rv = test_sd_card_print_dir( TEST_SD_CARD_MOUNT_POINT, 0);
+	RTEMS_CHECK_RV_TASK( rv, "Print directory");
+
+	(void) rtems_task_delete( RTEMS_SELF);
 
 	rv = mkdir( TEST_SD_CARD_DIRECTORY, S_IRWXU);
@@ -524,4 +499,6 @@
 	RTEMS_CHECK_RV_TASK( rv, "Print directory");
 
+	(void) rtems_task_delete( RTEMS_SELF);
+
 
 	#if 0
@@ -562,7 +539,8 @@
 	#endif
 
-	sc = rtems_task_delete( RTEMS_SELF);
-	RTEMS_CHECK_SC_TASK( sc, "rtems_task_delete");
-}
+	(void) rtems_task_delete( RTEMS_SELF);
+}
+
+#endif
 
 #define ITER 4
@@ -572,23 +550,33 @@
 static char outbuf [BUFSIZE];
 
+static void test_mpc55xx_edma_done( mpc55xx_edma_channel_entry *e, uint32_t error_status)
+{
+	rtems_semaphore_release( e->id);
+
+	if (error_status != 0) {
+		printk( "%s: Error status: 0x%08x\n", __func__, error_status);
+	}
+}
+
 static rtems_status_code test_mpc55xx_edma(void)
 {
 	rtems_status_code sc = RTEMS_SUCCESSFUL;
-	int rv = 0;
-	int channel = 0;
-	uint32_t error_status = 0;
-	rtems_id transfer_update;
+	mpc55xx_edma_channel_entry e = {
+		.channel = 0,
+		.done = test_mpc55xx_edma_done,
+		.id = RTEMS_ID_NONE
+	};
 
 	sc = rtems_semaphore_create (
 		rtems_build_name ( 'T', 'S', 'T', 'C'),
 		0,
-		RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+		RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_PRIORITY,
 		RTEMS_NO_PRIORITY,
-		&transfer_update
+		&e.id
 	);
 	RTEMS_CHECK_SC( sc, "rtems_semaphore_create");
 
-	rv = mpc55xx_edma_obtain_channel( channel, &error_status, transfer_update);
-	RTEMS_CHECK_RV( rv, "mpc55xx_edma_obtain_channel");
+	sc = mpc55xx_edma_obtain_channel( &e);
+	RTEMS_CHECK_RV( sc, "mpc55xx_edma_obtain_channel");
 
 	int i = 0;
@@ -600,26 +588,26 @@
 	rtems_cache_flush_multiple_data_lines( outbuf, BUFSIZE);
 
-	struct tcd_t tcd = MPC55XX_EDMA_TCD_DEFAULT;
+	struct tcd_t tcd = EDMA_TCD_DEFAULT;
 	tcd.SADDR = (uint32_t) &inbuf;
 	tcd.DADDR = (uint32_t) &outbuf;
 	tcd.NBYTES = BUFSIZE / ITER;
 	tcd.SLAST = -BUFSIZE;
-	tcd.CITER = ITER;
-	tcd.BITER = ITER;
-	tcd.INT_HALF = 1;
-
-	EDMA.TCD [channel] = tcd;
+	tcd.CDF.B.CITER = ITER;
+	tcd.BMF.B.BITER = ITER;
+	tcd.BMF.B.INT_HALF = 1;
+
+	EDMA.TCD [e.channel] = tcd;
 
 	while (1) {
 		while (1) {
-			if (EDMA.TCD [channel].DONE == 1) {
-				EDMA.TCD [channel].DONE = 0;
+			if (EDMA.TCD [e.channel].BMF.B.DONE == 1) {
+				EDMA.TCD [e.channel].BMF.B.DONE = 0;
 				printk( "%s: Done\n", __func__);
 				break;
-			} else if (EDMA.TCD [channel].ACTIVE == 0) {
-				EDMA.SSBR.R = channel;
-				printk( "%s: Start: %i (%i)\n", __func__, EDMA.TCD [channel].CITER, EDMA.TCD [channel].BITER);
+			} else if (EDMA.TCD [e.channel].BMF.B.ACTIVE == 0) {
+				EDMA.SSBR.R = e.channel;
+				printk( "%s: Start: %i (%i)\n", __func__, EDMA.TCD [e.channel].CDF.B.CITER, EDMA.TCD [e.channel].BMF.B.BITER);
 			}
-			sc = rtems_semaphore_obtain( transfer_update, RTEMS_WAIT, 10);
+			sc = rtems_semaphore_obtain( e.id, RTEMS_WAIT, 10);
 			if (sc == RTEMS_TIMEOUT) {
 				continue;
@@ -627,9 +615,10 @@
 			RTEMS_CHECK_SC( sc, "rtems_semaphore_obtain");
 		}
-		printk( "%s: Error status: 0x%08x\n", __func__, error_status);
-	}
-
-	return sc;
-}
+	}
+
+	return RTEMS_SUCCESSFUL;
+}
+
+#include <stdlib.h>
 
 static unsigned test_mpc55xx_intc_counter = 0;
@@ -668,9 +657,13 @@
 static rtems_task test_mpc55xx_intc( rtems_task_argument arg)
 {
+	rtems_status_code sc = RTEMS_SUCCESSFUL;
+	rtems_irq_connect_data e = {
+		.on = NULL,
+		.off = NULL,
+		.isOn = NULL
+	};
 	volatile int i = 0;
 	int p = 0;
 	unsigned s = 0;
-	rtems_irq_connect_data e;
-	rtems_status_code sc = RTEMS_SUCCESSFUL;
 
 	for (i = MPC55XX_IRQ_SOFTWARE_MIN, p = MPC55XX_INTC_MIN_PRIORITY; i <= MPC55XX_IRQ_SOFTWARE_MAX; ++i, ++p) {
@@ -685,10 +678,10 @@
 
 		e.hdl = test_mpc55xx_intc_handler_2;
-		if (BSP_install_rtems_shared_irq_handler( &e) != RTEMS_SUCCESSFUL) {
+		if (BSP_install_rtems_shared_irq_handler( &e) != 1) {
 			BSP_panic( "Handler install 2 failed");
 		}
 
 		e.hdl = test_mpc55xx_intc_handler_3;
-		if (BSP_install_rtems_shared_irq_handler( &e) != RTEMS_SUCCESSFUL) {
+		if (BSP_install_rtems_shared_irq_handler( &e) != 1) {
 			BSP_panic( "Handler install 3 failed");
 		}
Index: c/src/lib/libcpu/powerpc/ChangeLog
===================================================================
--- c/src/lib/libcpu/powerpc/ChangeLog	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libcpu/powerpc/ChangeLog	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -1,2 +1,10 @@
+2009-07-20	Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+	* Makefile.am, preinstall.am: Update for MPC55XX changes.
+	* mpc55xx/emios/emios.c, mpc55xx/include/emios.h: New files.
+	* mpc55xx/dspi/dspi.c, mpc55xx/edma/edma.c, mpc55xx/esci/esci.c,
+	mpc55xx/include/dspi.h, mpc55xx/include/edma.h, mpc55xx/include/irq.h,
+	mpc55xx/include/regs.h, mpc55xx/irq/irq.c: Changes throughout.
+
 2009-05-05	Jennifer Averett <jennifer.averett@OARcorp.com>
 
Index: c/src/lib/libcpu/powerpc/Makefile.am
===================================================================
--- c/src/lib/libcpu/powerpc/Makefile.am	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libcpu/powerpc/Makefile.am	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -420,4 +420,5 @@
 	mpc55xx/include/dspi.h \
 	mpc55xx/include/edma.h \
+	mpc55xx/include/emios.h \
 	mpc55xx/include/mpc55xx.h \
 	mpc55xx/include/esci.h \
@@ -434,10 +435,15 @@
 mpc55xx_fec_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
 
-# EMDA
+# eDMA
 noinst_PROGRAMS += mpc55xx/edma.rel
 mpc55xx_edma_rel_SOURCES = mpc55xx/edma/edma.c
 mpc55xx_edma_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
 
-# ESCI
+# eMIOS
+noinst_PROGRAMS += mpc55xx/emios.rel
+mpc55xx_emios_rel_SOURCES = mpc55xx/emios/emios.c
+mpc55xx_emios_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
+
+# eSCI
 noinst_PROGRAMS += mpc55xx/esci.rel
 mpc55xx_esci_rel_SOURCES = mpc55xx/esci/esci.c
Index: c/src/lib/libcpu/powerpc/mpc55xx/dspi/dspi.c
===================================================================
--- c/src/lib/libcpu/powerpc/mpc55xx/dspi/dspi.c	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libcpu/powerpc/mpc55xx/dspi/dspi.c	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -21,5 +21,4 @@
 #include <mpc55xx/regs.h>
 #include <mpc55xx/dspi.h>
-#include <mpc55xx/edma.h>
 #include <mpc55xx/mpc55xx.h>
 
@@ -112,4 +111,13 @@
 };
 
+static void mpc55xx_dspi_edma_done( mpc55xx_edma_channel_entry *e, uint32_t error_status)
+{
+	rtems_semaphore_release( e->id);
+
+	if (error_status != 0) {
+		RTEMS_SYSLOG_ERROR( "eDMA error: 0x%08x\n", error_status);
+	}
+}
+
 static mpc55xx_dspi_baudrate_scaler_entry mpc55xx_dspi_search_baudrate_scaler( uint32_t scaler, int min, int mid, int max)
 {
@@ -152,5 +160,5 @@
 	union DSPI_CTAR_tag ctar = MPC55XX_ZERO_FLAGS;
 	union DSPI_RSER_tag rser = MPC55XX_ZERO_FLAGS;
-	struct tcd_t tcd_push = MPC55XX_EDMA_TCD_DEFAULT;
+	struct tcd_t tcd_push = EDMA_TCD_DEFAULT;
 	int i = 0;
 
@@ -159,12 +167,12 @@
 		rtems_build_name ( 'S', 'P', 'I', 'R'),
 		0,
-		RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
-		RTEMS_NO_PRIORITY,
-		&e->edma_channel_receive_update
+		RTEMS_SIMPLE_BINARY_SEMAPHORE,
+		0,
+		&e->edma_receive.id
 	);
-	RTEMS_CHECK_SC( sc, "Create receive update semaphore");
-
-	sc = mpc55xx_edma_obtain_channel( e->edma_channel_receive, &e->edma_channel_receive_error, e->edma_channel_receive_update);
-	RTEMS_CHECK_SC( sc, "Obtain receive eDMA channel");
+	RTEMS_CHECK_SC( sc, "create receive update semaphore");
+
+	sc = mpc55xx_edma_obtain_channel( &e->edma_receive);
+	RTEMS_CHECK_SC( sc, "obtain receive eDMA channel");
 
 	/* eDMA transmit */
@@ -172,27 +180,27 @@
 		rtems_build_name ( 'S', 'P', 'I', 'T'),
 		0,
-		RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
-		RTEMS_NO_PRIORITY,
-		&e->edma_channel_transmit_update
+		RTEMS_SIMPLE_BINARY_SEMAPHORE,
+		0,
+		&e->edma_transmit.id
 	);
-	RTEMS_CHECK_SC( sc, "Create transmit update semaphore");
-
-	sc = mpc55xx_edma_obtain_channel( e->edma_channel_transmit, &e->edma_channel_transmit_error, e->edma_channel_transmit_update);
-	RTEMS_CHECK_SC( sc, "Obtain transmit eDMA channel");
-
-	sc = mpc55xx_edma_obtain_channel( e->edma_channel_push, NULL, RTEMS_ID_NONE);
-	RTEMS_CHECK_SC( sc, "Obtain push eDMA channel");
+	RTEMS_CHECK_SC( sc, "create transmit update semaphore");
+
+	sc = mpc55xx_edma_obtain_channel( &e->edma_transmit);
+	RTEMS_CHECK_SC( sc, "obtain transmit eDMA channel");
+
+	sc = mpc55xx_edma_obtain_channel( &e->edma_push);
+	RTEMS_CHECK_SC( sc, "obtain push eDMA channel");
 
 	tcd_push.SADDR = mpc55xx_dspi_push_data_address( e);
-	tcd_push.SSIZE = 2;
-	tcd_push.SOFF = 0;
+	tcd_push.SDF.B.SSIZE = 2;
+	tcd_push.SDF.B.SOFF = 0;
 	tcd_push.DADDR = (uint32_t) &e->regs->PUSHR.R;
-	tcd_push.DSIZE = 2;
-	tcd_push.DOFF = 0;
+	tcd_push.SDF.B.DSIZE = 2;
+	tcd_push.CDF.B.DOFF = 0;
 	tcd_push.NBYTES = 4;
-	tcd_push.CITER = 1;
-	tcd_push.BITER = 1;
-
-	EDMA.TCD [e->edma_channel_push] = tcd_push;
+	tcd_push.CDF.B.CITER = 1;
+	tcd_push.BMF.B.BITER = 1;
+
+	EDMA.TCD [e->edma_push.channel] = tcd_push;
 
 	/* Module Control Register */
@@ -325,6 +333,4 @@
 	mpc55xx_dspi_bus_entry *e = (mpc55xx_dspi_bus_entry *) bus;
 	union DSPI_CTAR_tag ctar = MPC55XX_ZERO_FLAGS;
-	uint32_t scaler = bsp_clock_speed / mode->baudrate;
-	mpc55xx_dspi_baudrate_scaler_entry bse = mpc55xx_dspi_search_baudrate_scaler( scaler, 0, MPC55XX_DSPI_BAUDRATE_SCALER_TABLE_SIZE / 2, MPC55XX_DSPI_BAUDRATE_SCALER_TABLE_SIZE);
 
 	if (mode->bits_per_char != 8) {
@@ -335,7 +341,4 @@
 
 	ctar.R = e->regs->CTAR [MPC55XX_DSPI_CTAR_DEFAULT].R;
-
-	ctar.B.PBR = bse.pbr;
-	ctar.B.BR = bse.br;
 
 	ctar.B.PCSSCK = 0;
@@ -347,4 +350,14 @@
 	ctar.B.CPOL = mode->clock_inv ? 1 : 0;
 	ctar.B.CPHA = mode->clock_phs ? 1 : 0;
+
+	if (mode->baudrate != e->baud) {
+		uint32_t scaler = bsp_clock_speed / mode->baudrate;
+		mpc55xx_dspi_baudrate_scaler_entry bse = mpc55xx_dspi_search_baudrate_scaler( scaler, 0, MPC55XX_DSPI_BAUDRATE_SCALER_TABLE_SIZE / 2, MPC55XX_DSPI_BAUDRATE_SCALER_TABLE_SIZE);
+
+		ctar.B.PBR = bse.pbr;
+		ctar.B.BR = bse.br;
+
+		e->baud = mode->baudrate;
+	}
 
 	e->regs->CTAR [MPC55XX_DSPI_CTAR_DEFAULT].R = ctar.R;
@@ -364,7 +377,7 @@
  *  out [shape=box,label="Output Buffer"];
  *  edge [color=red,fontcolor=red];
- *  push -> idle_push_data [label="Transmit Request",URL="\ref mpc55xx_dspi_bus_entry::edma_channel_transmit"];
- *  push -> out [label="Transmit Request",URL="\ref mpc55xx_dspi_bus_entry::edma_channel_transmit"];
- *  out -> push_data [label="Channel Link",URL="\ref mpc55xx_dspi_bus_entry::edma_channel_push"];
+ *  push -> idle_push_data [label="Transmit Request",URL="\ref mpc55xx_dspi_bus_entry::edma_transmit"];
+ *  push -> out [label="Transmit Request",URL="\ref mpc55xx_dspi_bus_entry::edma_transmit"];
+ *  out -> push_data [label="Channel Link",URL="\ref mpc55xx_dspi_bus_entry::edma_push"];
  *  edge [color=blue,fontcolor=blue];
  *  out -> push_data [label="Data"];
@@ -381,6 +394,6 @@
  *  in [shape=box,label="Input Buffer"];
  *  edge [color=red,fontcolor=red];
- *  pop -> nirvana [label="Receive Request",URL="\ref mpc55xx_dspi_bus_entry::edma_channel_receive"];
- *  pop -> in [label="Receive Request",URL="\ref mpc55xx_dspi_bus_entry::edma_channel_receive"];
+ *  pop -> nirvana [label="Receive Request",URL="\ref mpc55xx_dspi_bus_entry::edma_receive"];
+ *  pop -> in [label="Receive Request",URL="\ref mpc55xx_dspi_bus_entry::edma_receive"];
  *  edge [color=blue,fontcolor=blue];
  *  pop -> nirvana [label="Data"];
@@ -425,9 +438,9 @@
 		n_c = (int) mpc55xx_cache_aligned_size( in, (size_t) n);
 		if (n_c > EDMA_TCD_BITER_LINKED_SIZE) {
-			RTEMS_SYSLOG_WARNING( "Buffer size out of range, cannot use eDMA\n");
+			RTEMS_SYSLOG_WARNING( "buffer size out of range, cannot use eDMA\n");
 			n_nc = n;
 			n_c = 0;
 		} else if (n_nc + n_c != n) {
-			RTEMS_SYSLOG_WARNING( "Input buffer not proper cache aligned, cannot use eDMA\n");
+			RTEMS_SYSLOG_WARNING( "input buffer not proper cache aligned, cannot use eDMA\n");
 			n_nc = n;
 			n_c = 0;
@@ -511,6 +524,6 @@
 		unsigned char *in_c = in + n_nc;
 		const unsigned char *out_c = out + n_nc;
-		struct tcd_t tcd_transmit = MPC55XX_EDMA_TCD_DEFAULT;
-		struct tcd_t tcd_receive = MPC55XX_EDMA_TCD_DEFAULT;
+		struct tcd_t tcd_transmit = EDMA_TCD_DEFAULT;
+		struct tcd_t tcd_receive = EDMA_TCD_DEFAULT;
 
 		/* Cache operations */
@@ -523,50 +536,50 @@
 			mpc55xx_dspi_store_push_data( e);
 			tcd_transmit.SADDR = mpc55xx_dspi_push_data_address( e);
-			tcd_transmit.SSIZE = 2;
-			tcd_transmit.SOFF = 0;
+			tcd_transmit.SDF.B.SSIZE = 2;
+			tcd_transmit.SDF.B.SOFF = 0;
 			tcd_transmit.DADDR = (uint32_t) push;
-			tcd_transmit.DSIZE = 2;
-			tcd_transmit.DOFF = 0;
+			tcd_transmit.SDF.B.DSIZE = 2;
+			tcd_transmit.CDF.B.DOFF = 0;
 			tcd_transmit.NBYTES = 4;
-			tcd_transmit.CITER = n_c;
-			tcd_transmit.BITER = n_c;
+			tcd_transmit.CDF.B.CITER = n_c;
+			tcd_transmit.BMF.B.BITER = n_c;
 		} else {
-			EDMA.CDSBR.R = e->edma_channel_transmit;
+			EDMA.CDSBR.R = e->edma_transmit.channel;
 			tcd_transmit.SADDR = (uint32_t) out_c;
-			tcd_transmit.SSIZE = 0;
-			tcd_transmit.SOFF = 1;
+			tcd_transmit.SDF.B.SSIZE = 0;
+			tcd_transmit.SDF.B.SOFF = 1;
 			tcd_transmit.DADDR = mpc55xx_dspi_push_data_address( e) + 3;
-			tcd_transmit.DSIZE = 0;
-			tcd_transmit.DOFF = 0;
+			tcd_transmit.SDF.B.DSIZE = 0;
+			tcd_transmit.CDF.B.DOFF = 0;
 			tcd_transmit.NBYTES = 1;
-			tcd_transmit.CITERE_LINK = 1;
-			tcd_transmit.BITERE_LINK = 1;
-			tcd_transmit.MAJORLINKCH = e->edma_channel_push;
-			tcd_transmit.CITER = EDMA_TCD_LINK_AND_BITER( e->edma_channel_push, n_c);
-			tcd_transmit.BITER = EDMA_TCD_LINK_AND_BITER( e->edma_channel_push, n_c);
-			tcd_transmit.MAJORE_LINK = 1;
+			tcd_transmit.CDF.B.CITERE_LINK = 1;
+			tcd_transmit.BMF.B.BITERE_LINK = 1;
+			tcd_transmit.BMF.B.MAJORLINKCH = e->edma_push.channel;
+			tcd_transmit.CDF.B.CITER = EDMA_TCD_LINK_AND_BITER( e->edma_push.channel, n_c);
+			tcd_transmit.BMF.B.BITER = EDMA_TCD_LINK_AND_BITER( e->edma_push.channel, n_c);
+			tcd_transmit.BMF.B.MAJORE_LINK = 1;
 		}
-		tcd_transmit.D_REQ = 1;
-		tcd_transmit.INT_MAJ = 1;
-		EDMA.TCD [e->edma_channel_transmit] = tcd_transmit;
+		tcd_transmit.BMF.B.D_REQ = 1;
+		tcd_transmit.BMF.B.INT_MAJ = 1;
+		EDMA.TCD [e->edma_transmit.channel] = tcd_transmit;
 
 		/* Set receive TCD */
 		if (in == NULL) {
-			tcd_receive.DOFF = 0;
+			tcd_receive.CDF.B.DOFF = 0;
 			tcd_receive.DADDR = mpc55xx_dspi_nirvana_address( e);
 		} else {
-			tcd_receive.DOFF = 1;
+			tcd_receive.CDF.B.DOFF = 1;
 			tcd_receive.DADDR = (uint32_t) in_c;
 		}
 		tcd_receive.SADDR = (uint32_t) pop + 3;
-		tcd_receive.SSIZE = 0;
-		tcd_receive.SOFF = 0;
-		tcd_receive.DSIZE = 0;
+		tcd_receive.SDF.B.SSIZE = 0;
+		tcd_receive.SDF.B.SOFF = 0;
+		tcd_receive.SDF.B.DSIZE = 0;
 		tcd_receive.NBYTES = 1;
-		tcd_receive.D_REQ = 1;
-		tcd_receive.INT_MAJ = 1;
-		tcd_receive.CITER = n_c;
-		tcd_receive.BITER = n_c;
-		EDMA.TCD [e->edma_channel_receive] = tcd_receive;
+		tcd_receive.BMF.B.D_REQ = 1;
+		tcd_receive.BMF.B.INT_MAJ = 1;
+		tcd_receive.CDF.B.CITER = n_c;
+		tcd_receive.BMF.B.BITER = n_c;
+		EDMA.TCD [e->edma_receive.channel] = tcd_receive;
 
 		/* Clear request flags */
@@ -577,26 +590,14 @@
 
 		/* Enable hardware requests */
-		sc = mpc55xx_edma_enable_hardware_requests( e->edma_channel_receive, true);
-		RTEMS_CHECK_SC_RV( sc, "Enable receive hardware requests");
-		sc = mpc55xx_edma_enable_hardware_requests( e->edma_channel_transmit, true);
-		RTEMS_CHECK_SC_RV( sc, "Enable transmit hardware requests");
+		mpc55xx_edma_enable_hardware_requests( e->edma_receive.channel, true);
+		mpc55xx_edma_enable_hardware_requests( e->edma_transmit.channel, true);
 
 		/* Wait for transmit update */
-		sc = rtems_semaphore_obtain( e->edma_channel_transmit_update, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
-		RTEMS_CHECK_SC_RV( sc, "Transmit update");
-		if (e->edma_channel_transmit_error != 0) {
-			RTEMS_SYSLOG_ERROR( "Transmit error status: 0x%08x\n", e->edma_channel_transmit_error);
-			e->edma_channel_transmit_error = 0;
-			return -RTEMS_IO_ERROR;
-		}
+		sc = rtems_semaphore_obtain( e->edma_transmit.id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+		RTEMS_CHECK_SC_RV( sc, "transmit update");
 
 		/* Wait for receive update */
-		sc = rtems_semaphore_obtain( e->edma_channel_receive_update, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
-		RTEMS_CHECK_SC_RV( sc, "Receive update");
-		if (e->edma_channel_receive_error != 0) {
-			RTEMS_SYSLOG_ERROR( "Receive error status: 0x%08x\n", e->edma_channel_receive_error);
-			e->edma_channel_receive_error = 0;
-			return -RTEMS_IO_ERROR;
-		}
+		sc = rtems_semaphore_obtain( e->edma_receive.id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+		RTEMS_CHECK_SC_RV( sc, "receive update");
 	}
 
@@ -660,5 +661,6 @@
 };
 
-mpc55xx_dspi_bus_entry mpc55xx_dspi_bus_table [MPC55XX_DSPI_NUMBER] = { {
+mpc55xx_dspi_bus_entry mpc55xx_dspi_bus_table [MPC55XX_DSPI_NUMBER] = {
+	{
 		/* DSPI A */
 		.bus = {
@@ -669,14 +671,23 @@
 		.bus_number = 0,
 		.regs = &DSPI_A,
-		.master = 1,
+		.master = true,
 		.push_data = MPC55XX_ZERO_FLAGS,
-		.edma_channel_transmit = 32,
-		.edma_channel_push = 43,
-		.edma_channel_receive = 33,
-		.edma_channel_transmit_update = 0,
-		.edma_channel_receive_update = 0,
-		.edma_channel_transmit_error = 0,
-		.edma_channel_receive_error = 0,
+		.edma_transmit = {
+			.channel = 32,
+			.done = mpc55xx_dspi_edma_done,
+			.id = RTEMS_ID_NONE
+		},
+		.edma_push = {
+			.channel = 43,
+			.done = mpc55xx_dspi_edma_done,
+			.id = RTEMS_ID_NONE
+		},
+		.edma_receive = {
+			.channel = 33,
+			.done = mpc55xx_dspi_edma_done,
+			.id = RTEMS_ID_NONE
+		},
 		.idle_char = 0xffffffff,
+		.baud = 0
 	}, {
 		/* DSPI B */
@@ -688,14 +699,23 @@
 		.bus_number = 0,
 		.regs = &DSPI_B,
-		.master = 1,
+		.master = true,
 		.push_data = MPC55XX_ZERO_FLAGS,
-		.edma_channel_transmit = 12,
-		.edma_channel_push = 10,
-		.edma_channel_receive = 13,
-		.edma_channel_transmit_update = 0,
-		.edma_channel_receive_update = 0,
-		.edma_channel_transmit_error = 0,
-		.edma_channel_receive_error = 0,
+		.edma_transmit = {
+			.channel = 12,
+			.done = mpc55xx_dspi_edma_done,
+			.id = RTEMS_ID_NONE
+		},
+		.edma_push = {
+			.channel = 10,
+			.done = mpc55xx_dspi_edma_done,
+			.id = RTEMS_ID_NONE
+		},
+		.edma_receive = {
+			.channel = 13,
+			.done = mpc55xx_dspi_edma_done,
+			.id = RTEMS_ID_NONE
+		},
 		.idle_char = 0xffffffff,
+		.baud = 0
 	}, {
 		/* DSPI C */
@@ -707,14 +727,23 @@
 		.bus_number = 0,
 		.regs = &DSPI_C,
-		.master = 1,
+		.master = true,
 		.push_data = MPC55XX_ZERO_FLAGS,
-		.edma_channel_transmit = 14,
-		.edma_channel_push = 11,
-		.edma_channel_receive = 15,
-		.edma_channel_transmit_update = 0,
-		.edma_channel_receive_update = 0,
-		.edma_channel_transmit_error = 0,
-		.edma_channel_receive_error = 0,
+		.edma_transmit = {
+			.channel = 14,
+			.done = mpc55xx_dspi_edma_done,
+			.id = RTEMS_ID_NONE
+		},
+		.edma_push = {
+			.channel = 11,
+			.done = mpc55xx_dspi_edma_done,
+			.id = RTEMS_ID_NONE
+		},
+		.edma_receive = {
+			.channel = 15,
+			.done = mpc55xx_dspi_edma_done,
+			.id = RTEMS_ID_NONE
+		},
 		.idle_char = 0xffffffff,
+		.baud = 0
 	}, {
 		/* DSPI D */
@@ -726,14 +755,23 @@
 		.bus_number = 0,
 		.regs = &DSPI_D,
-		.master = 1,
+		.master = true,
 		.push_data = MPC55XX_ZERO_FLAGS,
-		.edma_channel_transmit = 16,
-		.edma_channel_push = 18,
-		.edma_channel_receive = 17,
-		.edma_channel_transmit_update = 0,
-		.edma_channel_receive_update = 0,
-		.edma_channel_transmit_error = 0,
-		.edma_channel_receive_error = 0,
+		.edma_transmit = {
+			.channel = 16,
+			.done = mpc55xx_dspi_edma_done,
+			.id = RTEMS_ID_NONE
+		},
+		.edma_push = {
+			.channel = 18,
+			.done = mpc55xx_dspi_edma_done,
+			.id = RTEMS_ID_NONE
+		},
+		.edma_receive = {
+			.channel = 17,
+			.done = mpc55xx_dspi_edma_done,
+			.id = RTEMS_ID_NONE
+		},
 		.idle_char = 0xffffffff,
-	},
+		.baud = 0
+	}
 };
Index: c/src/lib/libcpu/powerpc/mpc55xx/edma/edma.c
===================================================================
--- c/src/lib/libcpu/powerpc/mpc55xx/edma/edma.c	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libcpu/powerpc/mpc55xx/edma/edma.c	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -23,7 +23,8 @@
 #include <mpc55xx/mpc55xx.h>
 
+#include <string.h>
+
 #include <bsp/irq.h>
-
-#include <string.h>
+#include <bsp/utility.h>
 
 #define RTEMS_STATUS_CHECKS_USE_PRINTK
@@ -31,109 +32,100 @@
 #include <rtems/status-checks.h>
 
-#define MPC55XX_EDMA_CHANNEL_NUMBER 64
-#define MPC55XX_EDMA_INVALID_CHANNEL UINT8_MAX
-#define MPC55XX_EDMA_IS_CHANNEL_INVALID( i) ((i) < 0 || (i) >= MPC55XX_EDMA_CHANNEL_NUMBER)
-
-#define MPC55XX_EDMA_IRQ_PRIORITY MPC55XX_INTC_MIN_PRIORITY
-
-typedef struct {
-	uint8_t channel;
-	rtems_id transfer_update;
-	uint32_t *error_status;
-} mpc55xx_edma_channel_entry;
-
-static mpc55xx_edma_channel_entry mpc55xx_edma_channel_table [MPC55XX_EDMA_CHANNEL_NUMBER];
-
-static uint32_t mpc55xx_edma_channel_occupation_low = 0;
-
-static uint32_t mpc55xx_edma_channel_occupation_high = 0;
-
-static rtems_id mpc55xx_edma_channel_occupation_mutex = RTEMS_ID_NONE;
-
-static uint8_t mpc55xx_edma_irq_error_low_channel = 0;
-
-static uint8_t mpc55xx_edma_irq_error_high_channel = 32;
-
-static void mpc55xx_edma_irq_handler( rtems_vector_number vector, void *data)
-{
-	rtems_status_code sc = RTEMS_SUCCESSFUL;
-	mpc55xx_edma_channel_entry *e = (mpc55xx_edma_channel_entry *) data;
+#define MPC55XX_EDMA_CHANNEL_NUMBER 64U
+
+#define MPC55XX_EDMA_INVALID_CHANNEL MPC55XX_EDMA_CHANNEL_NUMBER
+
+#define MPC55XX_EDMA_IS_CHANNEL_INVALID( i) ((unsigned) (i) >= MPC55XX_EDMA_CHANNEL_NUMBER)
+
+#define MPC55XX_EDMA_IS_CHANNEL_VALID( i) ((unsigned) (i) < MPC55XX_EDMA_CHANNEL_NUMBER)
+
+#define MPC55XX_EDMA_IRQ_PRIORITY MPC55XX_INTC_DEFAULT_PRIORITY
+
+#define MPC55XX_EDMA_CHANNEL_FLAG( channel) ((uint64_t) 1 << (channel))
+
+static uint64_t mpc55xx_edma_channel_occupation = 0;
+
+static rtems_chain_control mpc55xx_edma_channel_chain;
+
+static void mpc55xx_edma_interrupt_handler( rtems_vector_number vector, void *arg)
+{
+	mpc55xx_edma_channel_entry *e = (mpc55xx_edma_channel_entry *) arg;
+
 #ifdef DEBUG
 	uint32_t citer = EDMA.TCD [e->channel].CITERE_LINK ? EDMA.TCD [e->channel].CITER & EDMA_TCD_BITER_LINKED_MASK : EDMA.TCD [e->channel].CITER;
-	RTEMS_DEBUG_PRINT( "Channel %i (CITER = %i)\n", e->channel, citer);
+	RTEMS_DEBUG_PRINT( "channel %i (CITER = %i)\n", e->channel, citer);
 #endif /* DEBUG */
-	EDMA.CIRQR.R = e->channel;
-	sc = rtems_semaphore_release( e->transfer_update);
-	RTEMS_SYSLOG_WARNING_SC( sc, "Transfer update semaphore release");
-}
-
-static void mpc55xx_edma_irq_update_error_table( uint8_t *link_table, uint8_t *error_table, int channel)
-{
-	int i = 0;
-	error_table [channel] = 1;
-	for (i = 0; i < MPC55XX_EDMA_CHANNEL_NUMBER; ++i) {
-		if (channel == link_table [i] && error_table [i] == 0) {
-			mpc55xx_edma_irq_update_error_table( link_table, error_table, i);
-		}
-	}
-}
-
-static void mpc55xx_edma_irq_error_handler( rtems_vector_number vector, void *data)
-{
-	rtems_status_code sc = RTEMS_SUCCESSFUL;
-	uint8_t channel_start = *((uint8_t *) data);
-	uint8_t channel_end = (uint8_t) (channel_start + 32);
-	int i = 0;
-	uint32_t mask = 0x1;
-	uint32_t error_register = 0;
-	uint8_t channel_link_table [MPC55XX_EDMA_CHANNEL_NUMBER];
-	uint8_t channel_error_table [MPC55XX_EDMA_CHANNEL_NUMBER];
-
-	/* Error register */
-	if (channel_start < 32) {
-		error_register = EDMA.ERL.R;
-	} else if (channel_start < 64) {
-		error_register = EDMA.ERH.R;
-	}
-	RTEMS_DEBUG_PRINT( "Error register %s: 0x%08x\n", channel_start < 32 ? "low" : "high", error_register);
-
-	/* Fill channel link table */
-	for (i = 0; i < MPC55XX_EDMA_CHANNEL_NUMBER; ++i) {
-		if (EDMA.TCD [i].BITERE_LINK && EDMA.TCD [i].CITER != EDMA.TCD [i].BITER) {
-			channel_link_table [i] = (uint8_t) EDMA_TCD_BITER_LINK( i);
-		} else if (EDMA.TCD [i].MAJORE_LINK && EDMA.TCD [i].CITER == EDMA.TCD [i].BITER) {
-			channel_link_table [i] = EDMA.TCD [i].MAJORLINKCH;
-		} else {
-			channel_link_table [i] = MPC55XX_EDMA_INVALID_CHANNEL;
-		}
-		channel_error_table [i] = 0;
-	}
-
-	/* Search for channels with errors */
-	for (i = channel_start; i < channel_end; ++i) {
-		if ((error_register & mask) != 0) {
-			mpc55xx_edma_irq_update_error_table( channel_link_table, channel_error_table, i);
-		}
-		mask <<= 1;
-	}
+
+	/* Clear interrupt */
+	EDMA.CIRQR.R = (uint8_t) e->channel;
+
+	/* Notify user */
+	e->done( e, 0);
+}
+
+static void mpc55xx_edma_interrupt_error_handler( rtems_vector_number vector, void *arg)
+{
+	rtems_chain_control *chain = &mpc55xx_edma_channel_chain;
+	rtems_chain_node *node = chain->first;
+	unsigned i = 0;
+	uint64_t error_status = EDMA.ESR.R;
+	uint64_t error_channels = ((uint64_t) EDMA.ERH.R << 32) | EDMA.ERL.R;
+	uint64_t error_channels_update = 0;
+
+	RTEMS_DEBUG_PRINT( "error channels: %08x %08x\n", (unsigned) (error_channels >> 32), (unsigned) error_channels);
+
+	/* Mark all channels that are linked to a channel with errors */
+	do {
+		error_channels_update = 0;
+
+		for (i = 0; i < MPC55XX_EDMA_CHANNEL_NUMBER; ++i) {
+			uint64_t channel_flags = 0;
+			unsigned minor_link = i;
+			unsigned major_link = i;
+
+			/* Check if we have linked channels */
+			if (EDMA.TCD [i].BMF.B.BITERE_LINK) {
+				minor_link = EDMA_TCD_BITER_LINK( i);
+			}
+			if (EDMA.TCD [i].BMF.B.MAJORE_LINK) {
+				major_link = EDMA.TCD [i].BMF.B.MAJORLINKCH;
+			}
+
+			/* Set flags related to this channel */
+			channel_flags = MPC55XX_EDMA_CHANNEL_FLAG( i) | MPC55XX_EDMA_CHANNEL_FLAG( minor_link) | MPC55XX_EDMA_CHANNEL_FLAG( major_link);
+
+			/* Any errors in these channels? */
+			if (IS_ANY_FLAG_SET( error_channels, channel_flags)) {
+				/* Get new error channels */
+				uint64_t update = (error_channels & channel_flags) ^ channel_flags;
+
+				/* Update error channels */
+				error_channels = SET_FLAGS( error_channels, channel_flags);
+
+				/* Contribute to the update of this round */
+				error_channels_update = SET_FLAGS( error_channels_update, update);
+			}
+		}
+	} while (error_channels_update != 0);
+
+	RTEMS_DEBUG_PRINT( "error channels (all): %08x %08x\n", (unsigned) (error_channels >> 32), (unsigned) error_channels);
 
 	/* Process the channels related to errors */
-	error_register = EDMA.ESR.R;
-	for (i = 0; i < MPC55XX_EDMA_CHANNEL_NUMBER; ++i) {
-		if (channel_error_table [i]) {
-			mpc55xx_edma_channel_entry *e = &mpc55xx_edma_channel_table [i];
-			if (e->error_status != NULL) {
-				*e->error_status = error_register;
-			}
-			sc = mpc55xx_edma_enable_hardware_requests( i, false);
-			RTEMS_SYSLOG_ERROR_SC( sc, "Disable hardware requests");
-			sc = rtems_semaphore_release( e->transfer_update);
-			RTEMS_SYSLOG_WARNING_SC( sc, "Transfer update semaphore release");
-		}
+	while (!rtems_chain_is_tail( chain, node)) {
+		mpc55xx_edma_channel_entry *e = (mpc55xx_edma_channel_entry *) node;
+
+		if (IS_FLAG_SET( error_channels, MPC55XX_EDMA_CHANNEL_FLAG( e->channel))) {
+			mpc55xx_edma_enable_hardware_requests( e->channel, false);
+
+			/* Notify user */
+			e->done( e, error_status);
+		}
+
+		node = node->next;
 	}
 
 	/* Clear the error interrupt requests */
 	for (i = 0; i < MPC55XX_EDMA_CHANNEL_NUMBER; ++i) {
-		if (channel_error_table [i]) {
+		if (IS_FLAG_SET( error_channels, MPC55XX_EDMA_CHANNEL_FLAG( i))) {
 			EDMA.CER.R = (uint8_t) i;
 		}
@@ -141,28 +133,28 @@
 }
 
-rtems_status_code mpc55xx_edma_enable_hardware_requests( int channel, bool enable)
-{
-	if (MPC55XX_EDMA_IS_CHANNEL_INVALID( channel)) {
-		return RTEMS_INVALID_NUMBER;
-	}
-	if (enable) {
-		EDMA.SERQR.R = (uint8_t) channel;
+void mpc55xx_edma_enable_hardware_requests( unsigned channel, bool enable)
+{
+	if (MPC55XX_EDMA_IS_CHANNEL_VALID( channel)) {
+		if (enable) {
+			EDMA.SERQR.R = (uint8_t) channel;
+		} else {
+			EDMA.CERQR.R = (uint8_t) channel;
+		}
 	} else {
-		EDMA.CERQR.R = (uint8_t) channel;
-	}
-	return RTEMS_SUCCESSFUL;
-}
-
-rtems_status_code mpc55xx_edma_enable_error_interrupts( int channel, bool enable)
-{
-	if (MPC55XX_EDMA_IS_CHANNEL_INVALID( channel)) {
-		return RTEMS_INVALID_NUMBER;
-	}
-	if (enable) {
-		EDMA.SEEIR.R = channel;
+		RTEMS_SYSLOG_ERROR( "invalid channel number\n");
+	}
+}
+
+void mpc55xx_edma_enable_error_interrupts( unsigned channel, bool enable)
+{
+	if (MPC55XX_EDMA_IS_CHANNEL_VALID( channel)) {
+		if (enable) {
+			EDMA.SEEIR.R = (uint8_t) channel;
+		} else {
+			EDMA.CEEIR.R = (uint8_t) channel;
+		}
 	} else {
-		EDMA.CEEIR.R = channel;
-	}
-	return RTEMS_SUCCESSFUL;
+		RTEMS_SYSLOG_ERROR( "invalid channel number\n");
+	}
 }
 
@@ -170,15 +162,7 @@
 {
 	rtems_status_code sc = RTEMS_SUCCESSFUL;
-	int i = 0;
-
-	/* Channel occupation mutex */
-	sc = rtems_semaphore_create (
-		rtems_build_name ( 'D', 'M', 'A', 'O'),
-		1,
-		RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
-		RTEMS_NO_PRIORITY,
-		&mpc55xx_edma_channel_occupation_mutex
-	);
-	RTEMS_CHECK_SC( sc, "Create channel occupation mutex");
+
+	/* Initialize channel chain */
+	rtems_chain_initialize_empty( &mpc55xx_edma_channel_chain);
 
 	/* Arbitration mode: round robin */
@@ -189,91 +173,100 @@
 	memset( &EDMA.TCD [0], 0, sizeof( EDMA.TCD));
 
-	/* Channel table */
-	for (i = 0; i < MPC55XX_EDMA_CHANNEL_NUMBER; ++i) {
-		mpc55xx_edma_channel_table [i].channel = i;
-		mpc55xx_edma_channel_table [i].transfer_update = RTEMS_ID_NONE;
-		mpc55xx_edma_channel_table [i].error_status = NULL;
-	}
-
-	/* Error interrupt handler */
+	/* Error interrupt handlers */
 	sc = mpc55xx_interrupt_handler_install(
 		MPC55XX_IRQ_EDMA_ERROR_LOW,
-		MPC55XX_EDMA_IRQ_PRIORITY,
 		"eDMA Error (Low)",
 		RTEMS_INTERRUPT_UNIQUE,
-		mpc55xx_edma_irq_error_handler,
-		&mpc55xx_edma_irq_error_low_channel
-	);
-	RTEMS_CHECK_SC( sc, "Install low error interrupt handler");
+		MPC55XX_EDMA_IRQ_PRIORITY,
+		mpc55xx_edma_interrupt_error_handler,
+		NULL
+	);
+	RTEMS_CHECK_SC( sc, "install low error interrupt handler");
 	sc = mpc55xx_interrupt_handler_install(
 		MPC55XX_IRQ_EDMA_ERROR_HIGH,
-		MPC55XX_EDMA_IRQ_PRIORITY,
 		"eDMA Error (High)",
 		RTEMS_INTERRUPT_UNIQUE,
-		mpc55xx_edma_irq_error_handler,
-		&mpc55xx_edma_irq_error_high_channel
-	);
-	RTEMS_CHECK_SC( sc, "Install high error interrupt handler");
+		MPC55XX_EDMA_IRQ_PRIORITY,
+		mpc55xx_edma_interrupt_error_handler,
+		NULL
+	);
+	RTEMS_CHECK_SC( sc, "install high error interrupt handler");
 
 	return RTEMS_SUCCESSFUL;
 }
 
-rtems_status_code mpc55xx_edma_obtain_channel( int channel, uint32_t *error_status, rtems_id transfer_update)
+rtems_status_code mpc55xx_edma_obtain_channel( mpc55xx_edma_channel_entry *e)
 {
 	rtems_status_code sc = RTEMS_SUCCESSFUL;
-	int channel_occupied = 1;
-
-	if (MPC55XX_EDMA_IS_CHANNEL_INVALID( channel)) {
+	rtems_interrupt_level level;
+	uint64_t channel_occupation = 0;
+
+	if (MPC55XX_EDMA_IS_CHANNEL_INVALID( e->channel)) {
 		return RTEMS_INVALID_NUMBER;
 	}
 
-	/* Check occupation */
-	sc = rtems_semaphore_obtain( mpc55xx_edma_channel_occupation_mutex, RTEMS_WAIT, 0);
-	RTEMS_CHECK_SC( sc, "Obtain channel occupation mutex");
-	if (channel < 32) {
-		channel_occupied = mpc55xx_edma_channel_occupation_low & (0x1 << channel);
-		if (!channel_occupied) {
-			mpc55xx_edma_channel_occupation_low |= 0x1 << channel;
-		}
-	} else if (channel < 64) {
-		channel_occupied = mpc55xx_edma_channel_occupation_high & (0x1 << (channel - 32));
-		if (!channel_occupied) {
-			mpc55xx_edma_channel_occupation_high |= 0x1 << (channel - 32);
-		}
-	}
-	if (channel_occupied) {
-		sc = rtems_semaphore_release( mpc55xx_edma_channel_occupation_mutex);
-		RTEMS_SYSLOG_WARNING_SC( sc, "Release occupation mutex");
+	/* Test and set channel occupation flag */
+	rtems_interrupt_disable( level);
+	channel_occupation = mpc55xx_edma_channel_occupation;
+	if (IS_FLAG_CLEARED( channel_occupation, MPC55XX_EDMA_CHANNEL_FLAG( e->channel))) {
+		mpc55xx_edma_channel_occupation = SET_FLAG( channel_occupation, MPC55XX_EDMA_CHANNEL_FLAG( e->channel));
+	}
+	rtems_interrupt_enable( level);
+
+	/* Check channel occupation flag */
+	if (IS_FLAG_SET( channel_occupation, MPC55XX_EDMA_CHANNEL_FLAG( e->channel))) {
 		return RTEMS_RESOURCE_IN_USE;
-	} else {
-		sc = rtems_semaphore_release( mpc55xx_edma_channel_occupation_mutex);
-		RTEMS_CHECK_SC( sc, "Release channel occupation mutex");
-	}
-
-	/* Channel data */
-	mpc55xx_edma_channel_table [channel].transfer_update = transfer_update;
-	mpc55xx_edma_channel_table [channel].error_status = error_status;
+	}
 
 	/* Interrupt handler */
 	sc = mpc55xx_interrupt_handler_install(
-		MPC55XX_IRQ_EDMA_GET_REQUEST( channel),
-		MPC55XX_EDMA_IRQ_PRIORITY,
+		MPC55XX_IRQ_EDMA_GET_REQUEST( e->channel),
 		"eDMA Channel",
 		RTEMS_INTERRUPT_SHARED,
-		mpc55xx_edma_irq_handler,
-		&mpc55xx_edma_channel_table [channel]
-	);
-	RTEMS_CHECK_SC( sc, "Install channel interrupt handler");
+		MPC55XX_EDMA_IRQ_PRIORITY,
+		mpc55xx_edma_interrupt_handler,
+		e
+	);
+	RTEMS_CHECK_SC( sc, "install channel interrupt handler");
 
 	/* Enable error interrupts */
-	sc = mpc55xx_edma_enable_error_interrupts( channel, true);
-	RTEMS_CHECK_SC( sc, "Enable error interrupts");
+	mpc55xx_edma_enable_error_interrupts( e->channel, true);
+
+	/* Prepend channel entry to channel list */
+	rtems_chain_prepend( &mpc55xx_edma_channel_chain, &e->node);
 
 	return RTEMS_SUCCESSFUL;
 }
 
-rtems_status_code mpc55xx_edma_release_channel( int channel)
-{
-	// TODO
-	return RTEMS_NOT_IMPLEMENTED;
-}
+rtems_status_code mpc55xx_edma_release_channel( mpc55xx_edma_channel_entry *e)
+{
+	rtems_status_code sc = RTEMS_SUCCESSFUL;
+	rtems_interrupt_level level;
+
+	/* Clear channel occupation flag */
+	rtems_interrupt_disable( level);
+	mpc55xx_edma_channel_occupation = CLEAR_FLAG( mpc55xx_edma_channel_occupation, MPC55XX_EDMA_CHANNEL_FLAG( e->channel));
+	rtems_interrupt_enable( level);
+
+	/* Disable hardware requests */
+	mpc55xx_edma_enable_hardware_requests( e->channel, false);
+
+	/* Disable error interrupts */
+	mpc55xx_edma_enable_error_interrupts( e->channel, false);
+
+	/* Extract channel entry from channel chain */
+	rtems_chain_extract( &e->node);
+
+	/* Remove interrupt handler */
+	sc = rtems_interrupt_handler_remove(
+		MPC55XX_IRQ_EDMA_GET_REQUEST( e->channel),
+		mpc55xx_edma_interrupt_handler,
+		e
+	);
+	RTEMS_CHECK_SC( sc, "remove channel interrupt handler");
+
+	/* Notify user */
+	e->done( e, 0);
+
+	return RTEMS_SUCCESSFUL;
+}
Index: c/src/lib/libcpu/powerpc/mpc55xx/emios/emios.c
===================================================================
--- c/src/lib/libcpu/powerpc/mpc55xx/emios/emios.c	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
+++ c/src/lib/libcpu/powerpc/mpc55xx/emios/emios.c	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -0,0 +1,109 @@
+/**
+ * @file
+ *
+ * @ingroup mpc55xx
+ *
+ * @brief Enhanced Modular Input Output Subsystem (eMIOS).
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * 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 <mpc55xx/regs.h>
+#include <mpc55xx/emios.h>
+#include <mpc55xx/mpc55xx.h>
+
+#include <bsp/irq.h>
+#include <bsp/utility.h>
+
+#define RTEMS_STATUS_CHECKS_USE_PRINTK
+
+#include <rtems/status-checks.h>
+
+/**
+ * @brief Initialize the eMIOS module.
+ *
+ * The module is enabled.  It is configured to use the internal clock.  The
+ * global prescaler value is set to @a prescaler.  If the value is greater than
+ * the maximum the maxium value will be used instead.  A prescaler value of
+ * zero disables the clock.
+ *
+ * @note No protection against concurrent execution.
+ */
+void mpc55xx_emios_initialize( unsigned prescaler)
+{
+  union EMIOS_MCR_tag mcr = MPC55XX_ZERO_FLAGS;
+
+  /* Enable module */
+  mcr.B.MDIS = 0;
+
+  /* Disable debug mode */
+  mcr.B.FRZ = 1;
+
+  /* Enable global time base */
+  mcr.B.GTBE = 1;
+
+  /* Disable global prescaler (= disable clock) */
+  mcr.B.GPREN = 0;
+
+  /* Set MCR */
+  EMIOS.MCR.R = mcr.R;
+
+  /* Set OUDR */
+  EMIOS.OUDR.R = 0;
+
+  /* Set global prescaler value */
+  mpc55xx_emios_set_global_prescaler( prescaler);
+}
+
+/**
+ * @brief Returns the global prescaler value of the eMIOS module.
+ */
+unsigned mpc55xx_emios_global_prescaler( void)
+{
+  union EMIOS_MCR_tag mcr = EMIOS.MCR;
+
+  if (mcr.B.GPREN != 0) {
+    return mcr.B.GPRE + 1;
+  } else {
+    return 0;
+  }
+}
+
+/**
+ * @brief Sets the global prescaler value of the eMIOS module.
+ *
+ * The global prescaler value is set to @a prescaler.  If the value is greater
+ * than the maximum the maxium value will be used instead.  A prescaler value
+ * of zero disables the clock.
+ *
+ * @note No protection against concurrent execution.
+ */
+void mpc55xx_emios_set_global_prescaler( unsigned prescaler)
+{
+  union EMIOS_MCR_tag mcr = EMIOS.MCR;
+
+  /* Enable or disable the global prescaler */
+  mcr.B.GPREN = prescaler > 0 ? 1 : 0;
+
+  /* Set global prescaler value */
+  if (prescaler > 256) {
+    prescaler = 256;
+  } else if (prescaler < 1) {
+    prescaler = 1;
+  }
+  mcr.B.GPRE = prescaler - 1;
+
+  /* Set MCR */
+  EMIOS.MCR.R = mcr.R;
+}
Index: c/src/lib/libcpu/powerpc/mpc55xx/esci/esci.c
===================================================================
--- c/src/lib/libcpu/powerpc/mpc55xx/esci/esci.c	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libcpu/powerpc/mpc55xx/esci/esci.c	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -42,5 +42,5 @@
 #undef CR2
 
-#define MPC55XX_ESCI_IRQ_PRIORITY MPC55XX_INTC_MIN_PRIORITY
+#define MPC55XX_ESCI_IRQ_PRIORITY MPC55XX_INTC_DEFAULT_PRIORITY
 
 #define MPC55XX_ESCI_IS_MINOR_INVALD(minor) ((minor) < 0 || (minor) >= MPC55XX_ESCI_NUMBER)
@@ -74,10 +74,5 @@
  */
 static const struct termios mpc55xx_esci_termios_default = {
-	0,
-	0,
-	CS8 | CREAD | CLOCAL | B115200,
-	0,
-	0,
-	{ 0 }
+	.c_cflag = CS8 | CREAD | CLOCAL | B115200
 };
 
@@ -120,74 +115,109 @@
 	volatile union ESCI_DR_tag *data = &e->regs->DR;
 	union ESCI_SR_tag sr = MPC55XX_ZERO_FLAGS;
-
-	while (status->B.TDRE == 0) {
-		/* Wait */
-	}
-
-	/* Clear flag */
+	rtems_interrupt_level level;
+
+	/* Set clear flag */
 	sr.B.TDRE = 1;
-	status->R = sr.R;
-
-	/* Write */
-	data->B.D = c;
-}
-
-/** @} */
-
-/**
- * @name Termios Support
- * @{
- */
-
-/**
- * @brief Opens port @a minor.
- *
- * @return Status code.
- */
-static int mpc55xx_esci_termios_first_open( int major, int minor, void *arg)
-{
-	mpc55xx_esci_driver_entry *e = &mpc55xx_esci_driver_table [minor];
+
+	while (true) {
+		rtems_interrupt_disable( level);
+		if (status->B.TDRE != 0) {
+			/* Clear flag */
+			status->R = sr.R;
+
+			/* Write */
+			data->B.D = c;
+
+			/* Done */
+			rtems_interrupt_enable( level);
+			break;
+		}
+		rtems_interrupt_enable( level);
+
+		while (status->B.TDRE == 0) {
+			/* Wait */
+		}
+	}
+}
+
+static inline void mpc55xx_esci_interrupts_enable( mpc55xx_esci_driver_entry *e)
+{
 	union ESCI_CR1_tag cr1 = MPC55XX_ZERO_FLAGS;
-	struct rtems_termios_tty *tty = ((rtems_libio_open_close_args_t *) arg)->iop->data1;
-
-	/* Check minor number */
-	if (MPC55XX_ESCI_IS_MINOR_INVALD( minor)) {
-		return RTEMS_INVALID_NUMBER;
-	}
-
-	/* Connect TTY */
-	e->tty = tty;	
-
-	/* Enable interrupts */
-	if (MPC55XX_ESCI_USE_INTERRUPTS( e)) {
-		cr1.R = e->regs->CR1.R;
-		cr1.B.RIE = 1;
-		cr1.B.TIE = 1;
-		e->regs->CR1.R = cr1.R;
-	}
-
-	return RTEMS_SUCCESSFUL;
-}
-
-/**
- * @brief Closes port @a minor.
- *
- * @return Status code.
- */
-static int mpc55xx_esci_termios_last_close( int major, int minor, void* arg)
-{
-	mpc55xx_esci_driver_entry *e = &mpc55xx_esci_driver_table [minor];
+	rtems_interrupt_level level;
+
+	rtems_interrupt_disable( level);
+	cr1.R = e->regs->CR1.R;
+	cr1.B.RIE = 1;
+	cr1.B.TIE = 1;
+	e->regs->CR1.R = cr1.R;
+	rtems_interrupt_enable( level);
+}
+
+static inline void mpc55xx_esci_interrupts_disable( mpc55xx_esci_driver_entry *e)
+{
 	union ESCI_CR1_tag cr1 = MPC55XX_ZERO_FLAGS;
-
-	/* Check minor number */
-	if (MPC55XX_ESCI_IS_MINOR_INVALD( minor)) {
-		return RTEMS_INVALID_NUMBER;
-	}
-
-	/* Disable interrupts */
+	rtems_interrupt_level level;
+
+	rtems_interrupt_disable( level);
 	cr1.R = e->regs->CR1.R;
 	cr1.B.RIE = 0;
 	cr1.B.TIE = 0;
 	e->regs->CR1.R = cr1.R;
+	rtems_interrupt_enable( level);
+}
+
+/** @} */
+
+/**
+ * @name Termios Support
+ * @{
+ */
+
+/**
+ * @brief Opens port @a minor.
+ *
+ * @return Status code.
+ */
+static int mpc55xx_esci_termios_first_open( int major, int minor, void *arg)
+{
+	int rv = 0;
+	mpc55xx_esci_driver_entry *e = &mpc55xx_esci_driver_table [minor];
+	struct rtems_termios_tty *tty = ((rtems_libio_open_close_args_t *) arg)->iop->data1;
+
+	/* Check minor number */
+	if (MPC55XX_ESCI_IS_MINOR_INVALD( minor)) {
+		return RTEMS_INVALID_NUMBER;
+	}
+
+	/* Connect TTY */
+	e->tty = tty;	
+
+	/* Enable interrupts */
+	if (MPC55XX_ESCI_USE_INTERRUPTS( e)) {
+		mpc55xx_esci_interrupts_enable( e);
+	}
+
+	rv = rtems_termios_set_initial_baud( e->tty, 115200);
+	RTEMS_CHECK_RV_SC( rv, "Set initial baud");
+
+	return RTEMS_SUCCESSFUL;
+}
+
+/**
+ * @brief Closes port @a minor.
+ *
+ * @return Status code.
+ */
+static int mpc55xx_esci_termios_last_close( int major, int minor, void* arg)
+{
+	mpc55xx_esci_driver_entry *e = &mpc55xx_esci_driver_table [minor];
+
+	/* Check minor number */
+	if (MPC55XX_ESCI_IS_MINOR_INVALD( minor)) {
+		return RTEMS_INVALID_NUMBER;
+	}
+
+	/* Disable interrupts */
+	mpc55xx_esci_interrupts_disable( e);
 
 	/* Disconnect TTY */
@@ -205,11 +235,18 @@
 {
 	mpc55xx_esci_driver_entry *e = &mpc55xx_esci_driver_table [minor];
-	
-	/* Check minor number */
-	if (MPC55XX_ESCI_IS_MINOR_INVALD( minor)) {
+	volatile union ESCI_SR_tag *status = &e->regs->SR;
+	volatile union ESCI_DR_tag *data = &e->regs->DR;
+	union ESCI_SR_tag sr = MPC55XX_ZERO_FLAGS;
+
+	if (status->B.RDRF == 0) {
 		return -1;
 	}
 
-	return (int) mpc55xx_esci_read_char( e);
+	/* Clear flag */
+	sr.B.RDRF = 1;
+	status->R = sr.R;
+
+	/* Read */
+	return data->B.D;
 }
 
@@ -232,7 +269,4 @@
 	for (i = 0; i < n; ++i) {
 		mpc55xx_esci_write_char( e, out [i]);
-		if (out [i] == '\n') {
-			mpc55xx_esci_write_char( e, '\r');
-		}
 	}
 
@@ -480,7 +514,7 @@
 				sc = mpc55xx_interrupt_handler_install(
 					e->irq_number,
-					MPC55XX_ESCI_IRQ_PRIORITY,
 					"eSCI",
 					RTEMS_INTERRUPT_UNIQUE,
+					MPC55XX_ESCI_IRQ_PRIORITY,
 					mpc55xx_esci_termios_interrupt_handler,
 					e
@@ -512,11 +546,5 @@
 			sc =  rtems_termios_open( major, minor, arg, &mpc55xx_esci_termios_callbacks_polled);
 		}
-		if (sc != RTEMS_SUCCESSFUL) {
-			return sc;
-		}
-		rv = rtems_termios_set_initial_baud( e->tty, 115200);
-		if (rv < 0) {
-			return RTEMS_IO_ERROR;
-		}
+		RTEMS_CHECK_SC( sc, "Open");
 	}
 
@@ -624,8 +652,11 @@
 {
 	mpc55xx_esci_driver_entry *e = &mpc55xx_esci_driver_table [mpc55xx_esci_output_char_minor];
+
+	mpc55xx_esci_interrupts_disable( e);
 	mpc55xx_esci_write_char( e, c);
 	if (c == '\n') {
 		mpc55xx_esci_write_char( e, '\r');
 	}
+	mpc55xx_esci_interrupts_enable( e);
 }
 
@@ -637,13 +668,15 @@
 static void mpc55xx_esci_output_char_init( char c)
 {
-	int console_found = 0;
+	bool console_found = false;
 	int i = 0;
+
 	for (i = 0; i < MPC55XX_ESCI_NUMBER; ++i) {
 		if (mpc55xx_esci_driver_table [i].console) {
-			console_found = 1;
+			console_found = true;
 			mpc55xx_esci_output_char_minor = i;
 			break;
 		}
 	}
+
 	if (console_found) {
 		BSP_output_char = mpc55xx_esci_output_char;
Index: c/src/lib/libcpu/powerpc/mpc55xx/include/dspi.h
===================================================================
--- c/src/lib/libcpu/powerpc/mpc55xx/include/dspi.h	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libcpu/powerpc/mpc55xx/include/dspi.h	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -29,4 +29,6 @@
 
 #include <rtems/libi2c.h>
+
+#include <mpc55xx/edma.h>
 
 #ifdef __cplusplus
@@ -65,5 +67,5 @@
 	 * @brief Selects SPI master or slave mode.
 	 */
-	int master;
+	bool master;
 
 	/**
@@ -73,43 +75,23 @@
 
 	/**
-	 * @brief eDMA channel for transmission.
+	 * @brief eDMA entry for transmission.
 	 *
-	 * The channel is fixed to particular DSPI.
+	 * The channel is fixed to a particular DSPI.
 	 */
-	int edma_channel_transmit;
+	mpc55xx_edma_channel_entry edma_transmit;
 
 	/**
-	 * @brief eDMA channel to generate the push data.
+	 * @brief eDMA entry for push data generation.
 	 *
-	 * You can choose any available channel.
+	 * You can choose every available channel.
 	 */
-	int edma_channel_push;
+	mpc55xx_edma_channel_entry edma_push;
 
 	/**
-	 * @brief eDMA channel for receiving.
+	 * @brief eDMA entry for receiving.
 	 *
-	 * The channel is fixed to particular DSPI.
+	 * The channel is fixed to a particular DSPI.
 	 */
-	int edma_channel_receive;
-
-	/**
-	 * @brief Semaphore ID for a transmit update.
-	 */
-	rtems_id edma_channel_transmit_update;
-
-	/**
-	 * @brief Semaphore ID for a receive update.
-	 */
-	rtems_id edma_channel_receive_update;
-
-	/**
-	 * @brief Transmit error status.
-	 */
-	uint32_t edma_channel_transmit_error;
-
-	/**
-	 * @brief Receive error status.
-	 */
-	uint32_t edma_channel_receive_error;
+	mpc55xx_edma_channel_entry edma_receive;
 
 	/**
@@ -117,4 +99,9 @@
 	 */
 	uint32_t idle_char;
+
+	/**
+	 * @brief Current baud.
+	 */
+	uint32_t baud;
 } mpc55xx_dspi_bus_entry;
 
Index: c/src/lib/libcpu/powerpc/mpc55xx/include/edma.h
===================================================================
--- c/src/lib/libcpu/powerpc/mpc55xx/include/edma.h	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libcpu/powerpc/mpc55xx/include/edma.h	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -23,6 +23,8 @@
 
 #include <stdbool.h>
+#include <stdint.h>
 
 #include <rtems.h>
+#include <rtems/chain.h>
 
 #ifdef __cplusplus
@@ -30,69 +32,20 @@
 #endif /* __cplusplus */
 
-#define MPC55XX_EDMA_TCD_DEFAULT { \
-	.SADDR = 0, \
-	.SMOD = 0, \
-	.SSIZE = 0x2, \
-	.SOFF = 4, \
-	.DADDR = 0, \
-	.DMOD = 0, \
-	.DSIZE = 0x2, \
-	.DOFF = 4, \
-	.NBYTES = 0, \
-	.SLAST = 0, \
-	.CITER = 1, \
-	.BITER = 1, \
-	.MAJORLINKCH = 0, \
-	.CITERE_LINK = 0, \
-	.BITERE_LINK = 0, \
-	.MAJORE_LINK = 0, \
-	.E_SG = 0, \
-	.DLAST_SGA = 0, \
-	.D_REQ = 0, \
-	.BWC = 0, \
-	.INT_HALF = 0, \
-	.INT_MAJ = 0, \
-	.DONE = 0, \
-	.ACTIVE = 0, \
-	.START = 0, \
-}
-
-#define MPC55XX_EDMA_TCD_ALT_DEFAULT { \
-	.SADDR = 0, \
-	.SMOD = 0, \
-	.SSIZE = 2, \
-	.DMOD = 0, \
-	.DSIZE = 2, \
-	.SOFF = 4, \
-	.NBYTES = 0, \
-	.SLAST = 0, \
-	.DADDR = 0, \
-	.CITERE_LINK = 0, \
-	.CITERLINKCH = 0, \
-	.CITER = 0, \
-	.DOFF = 4, \
-	.DLAST_SGA = 0, \
-	.BITERE_LINK = 0, \
-	.BITERLINKCH = 0, \
-	.BITER = 0, \
-	.BWC = 0, \
-	.MAJORLINKCH = 0, \
-	.DONE = 0, \
-	.ACTIVE = 0, \
-	.MAJORE_LINK = 0, \
-	.E_SG = 0, \
-	.D_REQ = 0, \
-	.INT_HALF = 0, \
-	.INT_MAJ = 0, \
-	.START = 0, \
-}
+typedef struct mpc55xx_edma_channel_entry {
+	rtems_chain_node node;
+	unsigned channel;
+	void (*done)( struct mpc55xx_edma_channel_entry *, uint32_t);
+	rtems_id id;
+} mpc55xx_edma_channel_entry;
 
 rtems_status_code mpc55xx_edma_init();
 
-rtems_status_code mpc55xx_edma_obtain_channel( int channel, uint32_t *error_status, rtems_id transfer_update);
+rtems_status_code mpc55xx_edma_obtain_channel( mpc55xx_edma_channel_entry *e);
 
-rtems_status_code mpc55xx_edma_enable_hardware_requests( int channel, bool enable);
+rtems_status_code mpc55xx_edma_release_channel( mpc55xx_edma_channel_entry *e);
 
-rtems_status_code mpc55xx_edma_enable_error_interrupts( int channel, bool enable);
+void mpc55xx_edma_enable_hardware_requests( unsigned channel, bool enable);
+
+void mpc55xx_edma_enable_error_interrupts( unsigned channel, bool enable);
 
 #ifdef __cplusplus
Index: c/src/lib/libcpu/powerpc/mpc55xx/include/emios.h
===================================================================
--- c/src/lib/libcpu/powerpc/mpc55xx/include/emios.h	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
+++ c/src/lib/libcpu/powerpc/mpc55xx/include/emios.h	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -0,0 +1,192 @@
+/**
+ * @file
+ *
+ * @ingroup mpc55xx
+ *
+ * @brief Enhanced Modular Input Output Subsystem (eMIOS).
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * 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 LIBCPU_POWERPC_MPC55XX_EMIOS_H
+#define LIBCPU_POWERPC_MPC55XX_EMIOS_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <rtems.h>
+#include <rtems/chain.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @name eMIOS - Modes
+ *
+ * @{
+ */
+
+#define MPC55XX_EMIOS_MODE_GPIO_INPUT 0U
+#define MPC55XX_EMIOS_MODE_GPIO_OUTPUT 1U
+#define MPC55XX_EMIOS_MODE_SAIC 2U
+#define MPC55XX_EMIOS_MODE_SAOC 3U
+#define MPC55XX_EMIOS_MODE_IPWM 4U
+#define MPC55XX_EMIOS_MODE_IPM 5U
+#define MPC55XX_EMIOS_MODE_DAOC_SECOND 6U
+#define MPC55XX_EMIOS_MODE_DAOC_BOTH 7U
+#define MPC55XX_EMIOS_MODE_PEA_ACCU_CONT 8U
+#define MPC55XX_EMIOS_MODE_PEA_ACCU_SINGLE 9U
+#define MPC55XX_EMIOS_MODE_PEA_COUNT_CONT 10U
+#define MPC55XX_EMIOS_MODE_PEA_COUNT_SINGLE 11U
+#define MPC55XX_EMIOS_MODE_QDEC_COUNT_DIR 12U
+#define MPC55XX_EMIOS_MODE_QDEC_PHASE 13U
+#define MPC55XX_EMIOS_MODE_WPTA 14U
+#define MPC55XX_EMIOS_MODE_RESERVED_15 15U
+#define MPC55XX_EMIOS_MODE_MC_UP_INT_CLK 16U
+#define MPC55XX_EMIOS_MODE_MC_UP_EXT_CLK 17U
+#define MPC55XX_EMIOS_MODE_RESERVED_18 18U
+#define MPC55XX_EMIOS_MODE_RESERVED_19 19U
+#define MPC55XX_EMIOS_MODE_MC_UP_DOWN_INT_CLK 20U
+#define MPC55XX_EMIOS_MODE_MC_UP_DOWN_EXT_CLK 21U
+#define MPC55XX_EMIOS_MODE_MC_UP_DOWN_CHANGE_INT_CLK 22U
+#define MPC55XX_EMIOS_MODE_MC_UP_DOWN_CHANGE_EXT_CLK 23U
+#define MPC55XX_EMIOS_MODE_OPWFM_B_IMMEDIATE 24U
+#define MPC55XX_EMIOS_MODE_OPWFM_B_NEXT_PERIOD 25U
+#define MPC55XX_EMIOS_MODE_OPWFM_AB_IMMEDIATE 26U
+#define MPC55XX_EMIOS_MODE_OPWFM_AB_NEXT_PERIOD 27U
+#define MPC55XX_EMIOS_MODE_OPWMC_TRAIL_TRAIL 28U
+#define MPC55XX_EMIOS_MODE_OPWMC_TRAIL_LEAD 29U
+#define MPC55XX_EMIOS_MODE_OPWMC_BOTH_TRAIL 30U
+#define MPC55XX_EMIOS_MODE_OPWMC_BOTH_LEAD 31U
+#define MPC55XX_EMIOS_MODE_OPWM_B_IMMEDIATE 32U
+#define MPC55XX_EMIOS_MODE_OPWM_B_NEXT_PERIOD 33U
+#define MPC55XX_EMIOS_MODE_OPWM_AB_IMMEDIATE 34U
+#define MPC55XX_EMIOS_MODE_OPWM_AB_NEXT_PERIOD 35U
+#define MPC55XX_EMIOS_MODE_RESERVED_36 36U
+#define MPC55XX_EMIOS_MODE_RESERVED_37 37U
+#define MPC55XX_EMIOS_MODE_RESERVED_38 38U
+#define MPC55XX_EMIOS_MODE_RESERVED_39 39U
+#define MPC55XX_EMIOS_MODE_RESERVED_40 40U
+#define MPC55XX_EMIOS_MODE_RESERVED_41 41U
+#define MPC55XX_EMIOS_MODE_RESERVED_42 42U
+#define MPC55XX_EMIOS_MODE_RESERVED_43 43U
+#define MPC55XX_EMIOS_MODE_RESERVED_44 44U
+#define MPC55XX_EMIOS_MODE_RESERVED_45 45U
+#define MPC55XX_EMIOS_MODE_RESERVED_46 46U
+#define MPC55XX_EMIOS_MODE_RESERVED_47 47U
+#define MPC55XX_EMIOS_MODE_RESERVED_48 48U
+#define MPC55XX_EMIOS_MODE_RESERVED_49 49U
+#define MPC55XX_EMIOS_MODE_RESERVED_50 50U
+#define MPC55XX_EMIOS_MODE_RESERVED_51 51U
+#define MPC55XX_EMIOS_MODE_RESERVED_52 52U
+#define MPC55XX_EMIOS_MODE_RESERVED_53 53U
+#define MPC55XX_EMIOS_MODE_RESERVED_54 54U
+#define MPC55XX_EMIOS_MODE_RESERVED_55 55U
+#define MPC55XX_EMIOS_MODE_RESERVED_56 56U
+#define MPC55XX_EMIOS_MODE_RESERVED_57 57U
+#define MPC55XX_EMIOS_MODE_RESERVED_58 58U
+#define MPC55XX_EMIOS_MODE_RESERVED_59 59U
+#define MPC55XX_EMIOS_MODE_RESERVED_60 60U
+#define MPC55XX_EMIOS_MODE_RESERVED_61 61U
+#define MPC55XX_EMIOS_MODE_RESERVED_62 62U
+#define MPC55XX_EMIOS_MODE_RESERVED_63 63U
+#define MPC55XX_EMIOS_MODE_RESERVED_64 64U
+#define MPC55XX_EMIOS_MODE_RESERVED_65 65U
+#define MPC55XX_EMIOS_MODE_RESERVED_66 66U
+#define MPC55XX_EMIOS_MODE_RESERVED_67 67U
+#define MPC55XX_EMIOS_MODE_RESERVED_68 68U
+#define MPC55XX_EMIOS_MODE_RESERVED_69 69U
+#define MPC55XX_EMIOS_MODE_RESERVED_70 70U
+#define MPC55XX_EMIOS_MODE_RESERVED_71 71U
+#define MPC55XX_EMIOS_MODE_RESERVED_72 72U
+#define MPC55XX_EMIOS_MODE_RESERVED_73 73U
+#define MPC55XX_EMIOS_MODE_RESERVED_74 74U
+#define MPC55XX_EMIOS_MODE_RESERVED_75 75U
+#define MPC55XX_EMIOS_MODE_RESERVED_76 76U
+#define MPC55XX_EMIOS_MODE_RESERVED_77 77U
+#define MPC55XX_EMIOS_MODE_RESERVED_78 78U
+#define MPC55XX_EMIOS_MODE_RESERVED_79 79U
+#define MPC55XX_EMIOS_MODE_MCB_UP_INT_CLK 80U
+#define MPC55XX_EMIOS_MODE_MCB_UP_EXT_CLK 81U
+#define MPC55XX_EMIOS_MODE_RESERVED_82 82U
+#define MPC55XX_EMIOS_MODE_RESERVED_83 83U
+#define MPC55XX_EMIOS_MODE_MCB_UP_DOWN_ONE_INT_CLK 84U
+#define MPC55XX_EMIOS_MODE_MCB_UP_DOWN_ONE_EXT_CLK 85U
+#define MPC55XX_EMIOS_MODE_MCB_UP_DOWN_BOTH_INT_CLK 86U
+#define MPC55XX_EMIOS_MODE_MCB_UP_DOWN_BOTH_EXT_CLK 87U
+#define MPC55XX_EMIOS_MODE_OPWFMB_B 88U
+#define MPC55XX_EMIOS_MODE_RESERVED_89 89U
+#define MPC55XX_EMIOS_MODE_OPWFMB_AB 90U
+#define MPC55XX_EMIOS_MODE_RESERVED_91 91U
+#define MPC55XX_EMIOS_MODE_OPWMCB_TRAIL_TRAIL 92U
+#define MPC55XX_EMIOS_MODE_OPWMCB_TRAIL_LEAD 93U
+#define MPC55XX_EMIOS_MODE_OPWMCB_BOTH_TRAIL 94U
+#define MPC55XX_EMIOS_MODE_OPWMCB_BOTH_LEAD 95U
+#define MPC55XX_EMIOS_MODE_OPWMB_SECOND 96U
+#define MPC55XX_EMIOS_MODE_RESERVED_97 97U
+#define MPC55XX_EMIOS_MODE_OPWMB_BOTH 98U
+#define MPC55XX_EMIOS_MODE_RESERVED_99 99U
+#define MPC55XX_EMIOS_MODE_RESERVED_100 100U
+#define MPC55XX_EMIOS_MODE_RESERVED_101 101U
+#define MPC55XX_EMIOS_MODE_RESERVED_102 102U
+#define MPC55XX_EMIOS_MODE_RESERVED_103 103U
+#define MPC55XX_EMIOS_MODE_RESERVED_104 104U
+#define MPC55XX_EMIOS_MODE_RESERVED_105 105U
+#define MPC55XX_EMIOS_MODE_RESERVED_106 106U
+#define MPC55XX_EMIOS_MODE_RESERVED_107 107U
+#define MPC55XX_EMIOS_MODE_RESERVED_108 108U
+#define MPC55XX_EMIOS_MODE_RESERVED_109 109U
+#define MPC55XX_EMIOS_MODE_RESERVED_110 110U
+#define MPC55XX_EMIOS_MODE_RESERVED_111 111U
+#define MPC55XX_EMIOS_MODE_RESERVED_112 112U
+#define MPC55XX_EMIOS_MODE_RESERVED_113 113U
+#define MPC55XX_EMIOS_MODE_RESERVED_114 114U
+#define MPC55XX_EMIOS_MODE_RESERVED_115 115U
+#define MPC55XX_EMIOS_MODE_RESERVED_116 116U
+#define MPC55XX_EMIOS_MODE_RESERVED_117 117U
+#define MPC55XX_EMIOS_MODE_RESERVED_118 118U
+#define MPC55XX_EMIOS_MODE_RESERVED_119 119U
+#define MPC55XX_EMIOS_MODE_RESERVED_120 120U
+#define MPC55XX_EMIOS_MODE_RESERVED_121 121U
+#define MPC55XX_EMIOS_MODE_RESERVED_122 122U
+#define MPC55XX_EMIOS_MODE_RESERVED_123 123U
+#define MPC55XX_EMIOS_MODE_RESERVED_124 124U
+#define MPC55XX_EMIOS_MODE_RESERVED_125 125U
+#define MPC55XX_EMIOS_MODE_RESERVED_126 126U
+#define MPC55XX_EMIOS_MODE_RESERVED_127 127U
+
+/** @} */
+
+#define MPC55XX_EMIOS_CHANNEL_NUMBER 24U
+
+#define MPC55XX_EMIOS_VALUE_MAX 0x00ffffffU
+
+#define MPC55XX_EMIOS_IS_CHANNEL_VALID( c) \
+  ((unsigned) (c) < MPC55XX_EMIOS_CHANNEL_NUMBER)
+
+#define MPC55XX_EMIOS_IS_CHANNEL_INVALID( c) \
+  (!MPC55XX_EMIOS_IS_CHANNEL_VALID( c))
+
+void mpc55xx_emios_initialize( unsigned prescaler);
+
+unsigned mpc55xx_emios_global_prescaler( void);
+
+void mpc55xx_emios_set_global_prescaler( unsigned prescaler);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBCPU_POWERPC_MPC55XX_EMIOS_H */
Index: c/src/lib/libcpu/powerpc/mpc55xx/include/irq.h
===================================================================
--- c/src/lib/libcpu/powerpc/mpc55xx/include/irq.h	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libcpu/powerpc/mpc55xx/include/irq.h	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -34,27 +34,44 @@
 
 /* Basics */
-#define MPC55XX_IRQ_MIN 0
-#define MPC55XX_IRQ_MAX 328
+#define MPC55XX_IRQ_MIN 0U
+#define MPC55XX_IRQ_MAX 328U
 #define MPC55XX_IRQ_BASE MPC55XX_IRQ_MIN
-#define MPC55XX_IRQ_NUMBER (MPC55XX_IRQ_MAX + 1)
+#define MPC55XX_IRQ_NUMBER (MPC55XX_IRQ_MAX + 1U)
 
 /* Software interrupts */
-#define MPC55XX_IRQ_SOFTWARE_MIN 0
-#define MPC55XX_IRQ_SOFTWARE_MAX 7
-#define MPC55XX_IRQ_SOFTWARE_NUMBER (MPC55XX_IRQ_SOFTWARE_MAX + 1)
+#define MPC55XX_IRQ_SOFTWARE_MIN 0U
+#define MPC55XX_IRQ_SOFTWARE_MAX 7U
+#define MPC55XX_IRQ_SOFTWARE_GET_INDEX( v) (v)
+#define MPC55XX_IRQ_SOFTWARE_GET_REQUEST( i) (i)
+#define MPC55XX_IRQ_SOFTWARE_NUMBER (MPC55XX_IRQ_SOFTWARE_MAX + 1U)
 
 /* eDMA interrupts */
-#define MPC55XX_IRQ_EDMA_ERROR_LOW 10
-#define MPC55XX_IRQ_EDMA_ERROR_HIGH 210
-#define MPC55XX_IRQ_EDMA_REQUEST_LOW_MIN 11
-#define MPC55XX_IRQ_EDMA_REQUEST_LOW_MAX 42
-#define MPC55XX_IRQ_EDMA_REQUEST_HIGH_MIN 211
-#define MPC55XX_IRQ_EDMA_REQUEST_HIGH_MAX 242
-#define MPC55XX_IRQ_EDMA_GET_CHANNEL( i) (((i) > MPC55XX_IRQ_EDMA_REQUEST_LOW_MAX) ? ((i) - MPC55XX_IRQ_EDMA_REQUEST_HIGH_MIN + 32) : ((i) - MPC55XX_IRQ_EDMA_REQUEST_LOW_MIN))
-#define MPC55XX_IRQ_EDMA_GET_REQUEST( c) (((c) > 31) ? ((c) + MPC55XX_IRQ_EDMA_REQUEST_HIGH_MIN - 32) : ((c) + MPC55XX_IRQ_EDMA_REQUEST_LOW_MIN))
+#define MPC55XX_IRQ_EDMA_ERROR_LOW 10U
+#define MPC55XX_IRQ_EDMA_ERROR_HIGH 210U
+#define MPC55XX_IRQ_EDMA_REQUEST_LOW_MIN 11U
+#define MPC55XX_IRQ_EDMA_REQUEST_LOW_MAX 42U
+#define MPC55XX_IRQ_EDMA_REQUEST_HIGH_MIN 211U
+#define MPC55XX_IRQ_EDMA_REQUEST_HIGH_MAX 242U
+#define MPC55XX_IRQ_EDMA_GET_CHANNEL( v) (((v) > MPC55XX_IRQ_EDMA_REQUEST_LOW_MAX) ? ((v) + 32U - MPC55XX_IRQ_EDMA_REQUEST_HIGH_MIN) : ((v) - MPC55XX_IRQ_EDMA_REQUEST_LOW_MIN))
+#define MPC55XX_IRQ_EDMA_GET_REQUEST( c) (((c) >= 32U) ? ((c) - 32U + MPC55XX_IRQ_EDMA_REQUEST_HIGH_MIN) : ((c) + MPC55XX_IRQ_EDMA_REQUEST_LOW_MIN))
+
+/* SIU external interrupts */
+#define MPC55XX_IRQ_SIU_EXTERNAL_0 46U
+#define MPC55XX_IRQ_SIU_EXTERNAL_1 47U
+#define MPC55XX_IRQ_SIU_EXTERNAL_2 48U
+#define MPC55XX_IRQ_SIU_EXTERNAL_3 49U
+#define MPC55XX_IRQ_SIU_EXTERNAL_4_15 50U
+
+/* eMIOS interrupts */
+#define MPC55XX_IRQ_EMIOS_REQUEST_LOW_MIN 51U
+#define MPC55XX_IRQ_EMIOS_REQUEST_LOW_MAX 66U
+#define MPC55XX_IRQ_EMIOS_REQUEST_HIGH_MIN 202U
+#define MPC55XX_IRQ_EMIOS_REQUEST_HIGH_MAX 209U
+#define MPC55XX_IRQ_EMIOS_GET_CHANNEL( v) (((v) > MPC55XX_IRQ_EMIOS_REQUEST_LOW_MAX) ? ((v) + 16U - MPC55XX_IRQ_EMIOS_REQUEST_HIGH_MIN) : ((v) - MPC55XX_IRQ_EMIOS_REQUEST_LOW_MIN))
+#define MPC55XX_IRQ_EMIOS_GET_REQUEST( c) (((c) >= 16U) ? ((c) - 16U + MPC55XX_IRQ_EMIOS_REQUEST_HIGH_MIN) : ((c) + MPC55XX_IRQ_EMIOS_REQUEST_LOW_MIN))
 
 /* Checks */
-#define MPC55XX_IRQ_IS_VALID(i) ((i) >= MPC55XX_IRQ_MIN && (i) <= MPC55XX_IRQ_MAX)
-#define MPC55XX_IRQ_IS_SOFTWARE(i) ((i) >= MPC55XX_IRQ_SOFTWARE_MIN && (i) <= MPC55XX_IRQ_SOFTWARE_MAX)
+#define MPC55XX_IRQ_IS_VALID(v) ((v) >= MPC55XX_IRQ_MIN && (v) <= MPC55XX_IRQ_MAX)
+#define MPC55XX_IRQ_IS_SOFTWARE(v) ((v) >= MPC55XX_IRQ_SOFTWARE_MIN && (v) <= MPC55XX_IRQ_SOFTWARE_MAX)
 
 /*
@@ -62,27 +79,27 @@
  */
 
-#define MPC55XX_INTC_INVALID_PRIORITY -1
-#define MPC55XX_INTC_DISABLED_PRIORITY 0
-#define MPC55XX_INTC_MIN_PRIORITY 1
-#define MPC55XX_INTC_MAX_PRIORITY 15
-#define MPC55XX_INTC_DEFAULT_PRIORITY MPC55XX_INTC_MIN_PRIORITY
+#define MPC55XX_INTC_MIN_PRIORITY 1U
+#define MPC55XX_INTC_MAX_PRIORITY 15U
+#define MPC55XX_INTC_DISABLED_PRIORITY 0U
+#define MPC55XX_INTC_INVALID_PRIORITY (MPC55XX_INTC_MAX_PRIORITY + 1)
+#define MPC55XX_INTC_DEFAULT_PRIORITY (MPC55XX_INTC_MIN_PRIORITY + 1)
 #define MPC55XX_INTC_IS_VALID_PRIORITY(p) ((p) >= MPC55XX_INTC_DISABLED_PRIORITY && (p) <= MPC55XX_INTC_MAX_PRIORITY)
 
 rtems_status_code mpc55xx_interrupt_handler_install(
 	rtems_vector_number vector,
-	int priority,
 	const char *info,
 	rtems_option options,
+	unsigned priority,
 	rtems_interrupt_handler handler,
 	void *arg
 );
 
-rtems_status_code mpc55xx_intc_get_priority( int i, int *p);
+rtems_status_code mpc55xx_intc_get_priority( rtems_vector_number vector, unsigned *priority);
 
-rtems_status_code mpc55xx_intc_set_priority( int i, int p);
+rtems_status_code mpc55xx_intc_set_priority( rtems_vector_number vector, unsigned priority);
 
-rtems_status_code mpc55xx_intc_raise_software_irq( int i);
+rtems_status_code mpc55xx_intc_raise_software_irq( rtems_vector_number vector);
 
-rtems_status_code mpc55xx_intc_clear_software_irq( int i);
+rtems_status_code mpc55xx_intc_clear_software_irq( rtems_vector_number vector);
 
 #ifdef __cplusplus
Index: c/src/lib/libcpu/powerpc/mpc55xx/include/regs.h
===================================================================
--- c/src/lib/libcpu/powerpc/mpc55xx/include/regs.h	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libcpu/powerpc/mpc55xx/include/regs.h	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -667,5 +667,5 @@
         } SRCR;
 
-        union {                 /* External Interrupt Status Register */
+        union SIU_EISR_tag {    /* External Interrupt Status Register */
             uint32_t R;
             struct {
@@ -690,5 +690,5 @@
         } EISR;
 
-        union {                 /* DMA/Interrupt Request Enable Register */
+        union SIU_DIRER_tag {   /* DMA/Interrupt Request Enable Register */
             uint32_t R;
             struct {
@@ -713,5 +713,5 @@
         } DIRER;
 
-        union {                 /* DMA/Interrupt Select Register */
+        union SIU_DIRSR_tag {   /* DMA/Interrupt Select Register */
             uint32_t R;
             struct {
@@ -724,5 +724,5 @@
         } DIRSR;
 
-        union {                 /* Overrun Status Register */
+        union SIU_OSR_tag {     /* Overrun Status Register */
             uint32_t R;
             struct {
@@ -747,5 +747,5 @@
         } OSR;
 
-        union {                 /* Overrun Request Enable Register */
+        union SIU_ORER_tag {    /* Overrun Request Enable Register */
             uint32_t R;
             struct {
@@ -770,5 +770,5 @@
         } ORER;
 
-        union {                 /* External IRQ Rising-Edge Event Enable Register */
+        union SIU_IREER_tag {   /* External IRQ Rising-Edge Event Enable Register */
             uint32_t R;
             struct {
@@ -793,5 +793,5 @@
         } IREER;
 
-        union {                 /* External IRQ Falling-Edge Event Enable Register */
+        union SIU_IFEER_tag {   /* External IRQ Falling-Edge Event Enable Register */
             uint32_t R;
             struct {
@@ -816,5 +816,5 @@
         } IFEER;
 
-        union {                 /* External IRQ Digital Filter Register */
+        union SIU_IDFR_tag {    /* External IRQ Digital Filter Register */
             uint32_t R;
             struct {
@@ -964,5 +964,5 @@
 /****************************************************************************/
     struct EMIOS_tag {
-        union {
+        union EMIOS_MCR_tag {
             uint32_t R;
             struct {
@@ -980,5 +980,5 @@
         } MCR;                  /* Module Configuration Register */
 
-        union {
+        union EMIOS_GFR_tag {
             uint32_t R;
             struct {
@@ -1011,5 +1011,5 @@
         } GFR;                  /* Global FLAG Register */
 
-        union {
+        union EMIOS_OUDR_tag {
             uint32_t R;
             struct {
@@ -1044,5 +1044,5 @@
         uint32_t emios_reserved[5];
 
-        struct {
+        struct EMIOS_CH_tag {
             union {
                 uint32_t R;    /* Channel A Data Register */
@@ -1057,5 +1057,5 @@
             } CCNTR;
 
-            union {
+            union EMIOS_CCR_tag {
                 uint32_t R;
                 struct {
@@ -1081,5 +1081,5 @@
             } CCR;              /* Channel Control Register */
 
-            union {
+            union EMIOS_CSR_tag {
                 uint32_t R;
                 struct {
@@ -2166,5 +2166,5 @@
         union {
             uint16_t R;
-        } SWTCR;                //Software Watchdog Timer Control
+        } SWTCR;                /* Software Watchdog Timer Control */
 
         uint8_t ecsm_reserved3[3];
@@ -2172,5 +2172,5 @@
         union {
             uint8_t R;
-        } SWTSR;                //SWT Service Register
+        } SWTSR;                /* SWT Service Register */
 
         uint8_t ecsm_reserved4[3];
@@ -2178,5 +2178,5 @@
         union {
             uint8_t R;
-        } SWTIR;                //SWT Interrupt Register
+        } SWTIR;                /* SWT Interrupt Register */
 
         uint32_t ecsm_reserved5a[1];
@@ -2211,5 +2211,5 @@
                 uint8_t EFNCR:1;
             } B;
-        } ECR;                  //ECC Configuration Register
+        } ECR;                  /* ECC Configuration Register */
 
         uint8_t mcm_reserved8[3];
@@ -2222,5 +2222,5 @@
                 uint8_t FNCE:1;
             } B;
-        } ESR;                  //ECC Status Register
+        } ESR;                  /* ECC Status Register */
 
         uint16_t ecsm_reserved9;
@@ -2235,5 +2235,5 @@
                 uint16_t ERRBIT:7;
             } B;
-        } EEGR;                 //ECC Error Generation Register
+        } EEGR;                 /* ECC Error Generation Register */
 
         uint32_t ecsm_reserved10;
@@ -2244,5 +2244,5 @@
                 uint32_t FEAR:32;
             } B;
-        } FEAR;                 //Flash ECC Address Register
+        } FEAR;                 /* Flash ECC Address Register */
 
         uint16_t ecsm_reserved11;
@@ -2254,5 +2254,5 @@
                 uint8_t FEMR:4;
             } B;
-        } FEMR;                 //Flash ECC Master Register
+        } FEMR;                 /* Flash ECC Master Register */
 
         union {
@@ -2266,5 +2266,5 @@
                 uint8_t PROT3:1;
             } B;
-        } FEAT;                 //Flash ECC Attributes Register
+        } FEAT;                 /* Flash ECC Attributes Register */
 
         union {
@@ -2273,5 +2273,5 @@
                 uint32_t FEDH:32;
             } B;
-        } FEDRH;                //Flash ECC Data High Register
+        } FEDRH;                /* Flash ECC Data High Register */
 
         union {
@@ -2280,5 +2280,5 @@
                 uint32_t FEDL:32;
             } B;
-        } FEDRL;                //Flash ECC Data Low Register
+        } FEDRL;                /* Flash ECC Data Low Register */
 
         union {
@@ -2287,5 +2287,5 @@
                 uint32_t REAR:32;
             } B;
-        } REAR;                 //RAM ECC Address
+        } REAR;                 /* RAM ECC Address */
 
         uint8_t ecsm_reserved12[2];
@@ -2297,5 +2297,5 @@
                 uint8_t REMR:4;
             } B;
-        } REMR;                 //RAM ECC Master
+        } REMR;                 /* RAM ECC Master */
 
         union {
@@ -2309,5 +2309,5 @@
                 uint8_t PROT3:1;
             } B;
-        } REAT;                 // RAM ECC Attributes Register
+        } REAT;                 /*  RAM ECC Attributes Register */
 
         union {
@@ -2316,5 +2316,5 @@
                 uint32_t REDH:32;
             } B;
-        } REDRH;                //RAM ECC Data High Register
+        } REDRH;                /* RAM ECC Data High Register */
 
         union {
@@ -2323,5 +2323,5 @@
                 uint32_t REDL:32;
             } B;
-        } REDRL;                //RAMECC Data Low Register
+        } REDRL;                /* RAMECC Data Low Register */
 
     };
@@ -2729,41 +2729,88 @@
             uint32_t SADDR;    /* source address */
 
-            uint16_t SMOD:5;   /* source address modulo */
-            uint16_t SSIZE:3;  /* source transfer size */
-            uint16_t DMOD:5;   /* destination address modulo */
-            uint16_t DSIZE:3;  /* destination transfer size */
-            int16_t SOFF;      /* signed source address offset */
+            /* Source and destination fields */
+            union tcd_SDF_tag {
+                uint32_t R;
+                struct {
+                    uint16_t SMOD:5;   /* source address modulo */
+                    uint16_t SSIZE:3;  /* source transfer size */
+                    uint16_t DMOD:5;   /* destination address modulo */
+                    uint16_t DSIZE:3;  /* destination transfer size */
+                    int16_t SOFF;      /* signed source address offset */
+                } B;
+            } SDF;
 
             uint32_t NBYTES;   /* inner (ÂminorÂ) byte count */
 
             int32_t SLAST;     /* last destination address adjustment, or
-
                                    scatter/gather address (if e_sg = 1) */
+
             uint32_t DADDR;    /* destination address */
 
-            uint16_t CITERE_LINK:1;
-            uint16_t CITER:15;
-
-            int16_t DOFF;      /* signed destination address offset */
+            /* CITER and destination fields */
+            union tcd_CDF_tag {
+                uint32_t R;
+                struct {
+                    uint16_t CITERE_LINK:1;
+                    uint16_t CITER:15;
+                    int16_t DOFF;      /* signed destination address offset */
+                } B;
+                struct {
+		    uint16_t CITERE_LINK:1;
+		    uint16_t CITERLINKCH:6;
+		    uint16_t CITER:9;
+                    int16_t DOFF;
+                } B_ALT;
+            } CDF;
 
             int32_t DLAST_SGA;
 
-            uint16_t BITERE_LINK:1;    /* beginning ("major") iteration count */
-            uint16_t BITER:15;
-
-            uint16_t BWC:2;    /* bandwidth control */
-            uint16_t MAJORLINKCH:6;    /* enable channel-to-channel link */
-            uint16_t DONE:1;   /* channel done */
-            uint16_t ACTIVE:1; /* channel active */
-            uint16_t MAJORE_LINK:1;    /* enable channel-to-channel link */
-            uint16_t E_SG:1;   /* enable scatter/gather descriptor */
-            uint16_t D_REQ:1;  /* disable ipd_req when done */
-            uint16_t INT_HALF:1;       /* interrupt on citer = (biter >> 1) */
-            uint16_t INT_MAJ:1;        /* interrupt on major loop completion */
-            uint16_t START:1;  /* explicit channel start */
+            /* BITER and misc fields */
+            union tcd_BMF_tag {
+                uint32_t R;
+                struct {
+                    uint32_t BITERE_LINK:1;    /* beginning ("major") iteration count */
+                    uint32_t BITER:15;
+                    uint32_t BWC:2;    /* bandwidth control */
+                    uint32_t MAJORLINKCH:6;    /* enable channel-to-channel link */
+                    uint32_t DONE:1;   /* channel done */
+                    uint32_t ACTIVE:1; /* channel active */
+                    uint32_t MAJORE_LINK:1;    /* enable channel-to-channel link */
+                    uint32_t E_SG:1;   /* enable scatter/gather descriptor */
+                    uint32_t D_REQ:1;  /* disable ipd_req when done */
+                    uint32_t INT_HALF:1;       /* interrupt on citer = (biter >> 1) */
+                    uint32_t INT_MAJ:1;        /* interrupt on major loop completion */
+                    uint32_t START:1;  /* explicit channel start */
+                } B;
+                struct {
+                    uint32_t BITERE_LINK:1;
+                    uint32_t BITERLINKCH:6;
+                    uint32_t BITER:9;
+                    uint32_t BWC:2;
+                    uint32_t MAJORLINKCH:6;
+                    uint32_t DONE:1;
+                    uint32_t ACTIVE:1;
+                    uint32_t MAJORE_LINK:1;
+                    uint32_t E_SG:1;
+                    uint32_t D_REQ:1;
+                    uint32_t INT_HALF:1;
+                    uint32_t INT_MAJ:1;
+                    uint32_t START:1;
+                } B_ALT;
+            } BMF;
         } TCD[64];              /* transfer_control_descriptor */
-
     };
 
+    static const struct tcd_t EDMA_TCD_DEFAULT = {
+        .SADDR = 0,
+        .SDF = { .R = 0 },
+        .NBYTES = 0,
+        .SLAST = 0,
+        .DADDR = 0,
+        .CDF = { .R = 0 },
+        .DLAST_SGA = 0,
+        .BMF = { .R = 0 } 
+    };
+
 #define EDMA_TCD_BITER_MASK 0x7fff
 
@@ -2776,48 +2823,6 @@
 #define EDMA_TCD_LINK_AND_BITER( link, biter) (((link) << 9) + ((biter) & EDMA_TCD_BITER_LINKED_MASK))
 
-#define EDMA_TCD_BITER_LINK( channel) (EDMA.TCD [(channel)].BITER >> 9)
-
-/* This is outside of the eDMA structure */
-/* There are 2 possible ways to use the citer bit field, this structure */
-/* uses the different format from the main structure.                   */
-    struct tcd_alt_t {
-        uint32_t SADDR;        /* source address */
-
-        uint16_t SMOD:5;       /* source address modulo */
-        uint16_t SSIZE:3;      /* source transfer size */
-        uint16_t DMOD:5;       /* destination address modulo */
-        uint16_t DSIZE:3;      /* destination transfer size */
-        int16_t SOFF;          /* signed source address offset */
-
-        uint32_t NBYTES;       /* inner (ÂminorÂ) byte count */
-
-        int32_t SLAST;         /* last destination address adjustment, or
-
-                                   scatter/gather address (if e_sg = 1) */
-        uint32_t DADDR;        /* destination address */
-
-        uint16_t CITERE_LINK:1;
-        uint16_t CITERLINKCH:6;
-        uint16_t CITER:9;
-
-        int16_t DOFF;          /* signed destination address offset */
-
-        int32_t DLAST_SGA;
-
-        uint16_t BITERE_LINK:1;        /* beginning (ÂmajorÂ) iteration count */
-        uint16_t BITERLINKCH:6;
-        uint16_t BITER:9;
-
-        uint16_t BWC:2;        /* bandwidth control */
-        uint16_t MAJORLINKCH:6;        /* enable channel-to-channel link */
-        uint16_t DONE:1;       /* channel done */
-        uint16_t ACTIVE:1;     /* channel active */
-        uint16_t MAJORE_LINK:1;        /* enable channel-to-channel link */
-        uint16_t E_SG:1;       /* enable scatter/gather descriptor */
-        uint16_t D_REQ:1;      /* disable ipd_req when done */
-        uint16_t INT_HALF:1;   /* interrupt on citer = (biter >> 1) */
-        uint16_t INT_MAJ:1;    /* interrupt on major loop completion */
-        uint16_t START:1;      /* explicit channel start */
-    };                          /* transfer_control_descriptor */
+#define EDMA_TCD_BITER_LINK( channel) (EDMA.TCD [(channel)].BMF.B.BITER >> 9)
+
 /****************************************************************************/
 /*                          MODULE : INTC                                   */
@@ -4250,4 +4255,103 @@
     };
 
+/****************************************************************************/
+/*                          MMU                                             */
+/****************************************************************************/
+    struct MMU_tag {
+        union {
+            uint32_t R;
+            struct {
+                uint32_t : 2;
+                uint32_t TLBSEL : 2;
+                uint32_t : 7;
+                uint32_t ESEL : 5;
+                uint32_t : 11;
+                uint32_t NV : 5;
+            } B;
+        } MAS0;
+
+        union {
+            uint32_t R;
+            struct {
+                uint32_t VALID : 1;
+                uint32_t IPROT : 1;
+                uint32_t : 6;
+                uint32_t TID : 8;
+                uint32_t : 3;
+                uint32_t TS : 1;
+                uint32_t TSIZ : 4;
+                uint32_t : 8;
+            } B;
+        } MAS1;
+
+        union {
+            uint32_t R;
+            struct {
+                uint32_t EPN : 20;
+                uint32_t : 7;
+                uint32_t W : 1;
+                uint32_t I : 1;
+                uint32_t M : 1;
+                uint32_t G : 1;
+                uint32_t E : 1;
+            } B;
+        } MAS2;
+
+        union {
+            uint32_t R;
+            struct {
+                uint32_t RPN : 20;
+                uint32_t : 2;
+                uint32_t U0 : 1;
+                uint32_t U1 : 1;
+                uint32_t U2 : 1;
+                uint32_t U3 : 1;
+                uint32_t UX : 1;
+                uint32_t SX : 1;
+                uint32_t UW : 1;
+                uint32_t SW : 1;
+                uint32_t UR : 1;
+                uint32_t SR : 1;
+            } B;
+        } MAS3;
+
+        union {
+            uint32_t R;
+            struct {
+                uint32_t : 2;
+                uint32_t TLBSELD : 2;
+                uint32_t : 10;
+                uint32_t TIDSELD : 2;
+                uint32_t : 4;
+                uint32_t TSIZED : 4;
+                uint32_t : 3;
+                uint32_t WD : 1;
+                uint32_t ID : 1;
+                uint32_t MD : 1;
+                uint32_t GD : 1;
+                uint32_t ED : 1;
+            } B;
+        } MAS4;
+
+        union {
+            uint32_t R;
+            struct {
+                uint32_t : 8;
+                uint32_t SPID : 8;
+                uint32_t : 15;
+                uint32_t SAS : 1;
+            } B;
+        } MAS6;
+    };
+
+    static const struct MMU_tag MMU_DEFAULT = {
+        .MAS0 = { .R = 0x10000000 },
+        .MAS1 = { .R = 0 },
+        .MAS2 = { .R = 0 },
+        .MAS3 = { .R = 0 },
+        .MAS4 = { .R = 0 },
+        .MAS6 = { .R = 0 }
+    };
+
 /* Define memories */
 
@@ -4309,5 +4413,5 @@
  *
  * Copyright:
- *	Freescale Semiconductor, INC. All Rights Reserved.
+ *  Freescale Semiconductor, INC. All Rights Reserved.
  *  You are hereby granted a copyright license to use, modify, and
  *  distribute the SOFTWARE so long as this entire notice is
Index: c/src/lib/libcpu/powerpc/mpc55xx/irq/irq.c
===================================================================
--- c/src/lib/libcpu/powerpc/mpc55xx/irq/irq.c	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libcpu/powerpc/mpc55xx/irq/irq.c	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -22,4 +22,5 @@
 
 #include <libcpu/raw_exception.h>
+#include <libcpu/powerpc-utility.h>
 
 #include <bsp/irq.h>
@@ -32,13 +33,13 @@
 
 /**
- * @brief Returns the priority @a p of IRQ @a i from the INTC.
+ * @brief Returns the priority @a priority of IRQ @a vector from the INTC.
  */
-rtems_status_code mpc55xx_intc_get_priority( int i, int *p)
+rtems_status_code mpc55xx_intc_get_priority( rtems_vector_number vector, unsigned *priority)
 {
-	if (MPC55XX_IRQ_IS_VALID( i)) {
-		*p = INTC.PSR [i].B.PRI;
+	if (MPC55XX_IRQ_IS_VALID( vector)) {
+		*priority = INTC.PSR [vector].B.PRI;
 		return RTEMS_SUCCESSFUL;
 	} else {
-		*p = MPC55XX_INTC_INVALID_PRIORITY;
+		*priority = MPC55XX_INTC_INVALID_PRIORITY;
 		return RTEMS_INVALID_NUMBER;
 	}	       
@@ -46,11 +47,11 @@
 
 /**
- * @brief Sets the priority of IRQ @a i to @a p at the INTC.
+ * @brief Sets the priority of IRQ @a vector to @a priority at the INTC.
  */
-rtems_status_code mpc55xx_intc_set_priority( int i, int p)
+rtems_status_code mpc55xx_intc_set_priority( rtems_vector_number vector, unsigned priority)
 {
-	if (MPC55XX_IRQ_IS_VALID( i) && MPC55XX_INTC_IS_VALID_PRIORITY( p)) {
-		INTC.PSR [i].B.PRI = p;
-		if (INTC.PSR [i].B.PRI == p) {
+	if (MPC55XX_IRQ_IS_VALID( vector) && MPC55XX_INTC_IS_VALID_PRIORITY( priority)) {
+		INTC.PSR [vector].B.PRI = priority;
+		if (INTC.PSR [vector].B.PRI == priority) {
 			return RTEMS_SUCCESSFUL;
 		} else {
@@ -63,10 +64,10 @@
 
 /**
- * @brief Raises the software IRQ with number @a i.
+ * @brief Raises the software IRQ with number @a vector.
  */
-rtems_status_code mpc55xx_intc_raise_software_irq( int i)
+rtems_status_code mpc55xx_intc_raise_software_irq( rtems_vector_number vector)
 {
-	if (MPC55XX_IRQ_IS_SOFTWARE( i)) {
-		INTC.SSCIR [i].B.SET = 1;
+	if (MPC55XX_IRQ_IS_SOFTWARE( vector)) {
+		INTC.SSCIR [vector].B.SET = 1;
 		return RTEMS_SUCCESSFUL;
 	} else {
@@ -76,10 +77,10 @@
 
 /**
- * @brief Clears the software IRQ with number @a i.
+ * @brief Clears the software IRQ with number @a vector.
  */
-rtems_status_code mpc55xx_intc_clear_software_irq( int i)
+rtems_status_code mpc55xx_intc_clear_software_irq( rtems_vector_number vector)
 {
-	if (MPC55XX_IRQ_IS_SOFTWARE( i)) {
-		INTC.SSCIR [i].B.CLR = 1;
+	if (MPC55XX_IRQ_IS_SOFTWARE( vector)) {
+		INTC.SSCIR [vector].B.CLR = 1;
 		return RTEMS_SUCCESSFUL;
 	} else {
@@ -93,16 +94,17 @@
 rtems_status_code mpc55xx_interrupt_handler_install(
 	rtems_vector_number vector,
-	int priority,
 	const char *info,
 	rtems_option options,
+	unsigned priority,
 	rtems_interrupt_handler handler,
 	void *arg
 )
 {
-	rtems_status_code sc = RTEMS_SUCCESSFUL;
+	if (MPC55XX_IRQ_IS_VALID( vector) && MPC55XX_INTC_IS_VALID_PRIORITY( priority)) {
+		rtems_status_code sc = RTEMS_SUCCESSFUL;
 
-	if (MPC55XX_IRQ_IS_VALID( vector) && MPC55XX_INTC_IS_VALID_PRIORITY( priority)) {
 		sc = rtems_interrupt_handler_install( vector, info, options, handler, arg);
 		RTEMS_CHECK_SC( sc, "Install interrupt handler");
+
 		return mpc55xx_intc_set_priority( vector, priority);
 	} else {
@@ -117,17 +119,14 @@
 {
 	/* Acknowlege interrupt request */
-	rtems_vector_number vector_number = INTC.IACKR.B.INTVEC;
+	rtems_vector_number vector = INTC.IACKR.B.INTVEC;
 
-	/* Save current interrupt level */
-	uint32_t level = _ISR_Get_level();
-
-	/* Enable all interrupts */
-	_ISR_Set_level( 0);
+	/* Save machine state and enable external exceptions */
+	uint32_t msr = ppc_external_exceptions_enable();
 
 	/* Dispatch interrupt handlers */
-	bsp_interrupt_handler_dispatch( vector_number);
+	bsp_interrupt_handler_dispatch( vector);
 
-	/* Restore interrupt level */
-	_ISR_Set_level( level);
+	/* Restore machine state */
+	ppc_external_exceptions_disable( msr);
 
 	/* End of interrupt */
Index: c/src/lib/libcpu/powerpc/preinstall.am
===================================================================
--- c/src/lib/libcpu/powerpc/preinstall.am	(revision 243596d65e9fc5541fc731c8ad7fc3fdc0bcaf9b)
+++ c/src/lib/libcpu/powerpc/preinstall.am	(revision d374492cc69fa8bd041852d868ae379b79c59ba4)
@@ -288,4 +288,8 @@
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc55xx/edma.h
 
+$(PROJECT_INCLUDE)/mpc55xx/emios.h: mpc55xx/include/emios.h $(PROJECT_INCLUDE)/mpc55xx/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/mpc55xx/emios.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc55xx/emios.h
+
 $(PROJECT_INCLUDE)/mpc55xx/mpc55xx.h: mpc55xx/include/mpc55xx.h $(PROJECT_INCLUDE)/mpc55xx/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/mpc55xx/mpc55xx.h
