changeset 2059:f929becf4af2

CAN driver, from Uwe Kindler
author gthomas
date Thu, 25 Aug 2005 13:40:35 +0000
parents 8d6df59beb34
children 0fd0cc06ae6e
files packages/devs/can/loop/current/ChangeLog packages/devs/can/loop/current/cdl/can_loop.cdl packages/devs/can/loop/current/src/loop_can.c packages/devs/can/loop/current/tests/can_nonblock.c packages/devs/can/loop/current/tests/can_overrun1.c packages/devs/can/loop/current/tests/can_overrun2.c packages/devs/can/loop/current/tests/can_rdwr.c packages/devs/can/loop/current/tests/can_test_aux.inl packages/devs/can/loop/current/tests/can_timeout.c packages/devs/can/loop/current/tests/can_txevent.c packages/devs/can/m68k/mcf52xx/current/ChangeLog packages/devs/can/m68k/mcf52xx/current/cdl/can_mcf52xx.cdl packages/devs/can/m68k/mcf52xx/current/src/can_mcf52xx.c packages/devs/can/m68k/mcf52xx/current/tests/can_test_aux.inl packages/devs/can/m68k/mcf52xx/current/tests/flexcan_load.c packages/devs/can/m68k/mcf52xx/current/tests/flexcan_remote.c packages/ecos.db packages/io/can/current/ChangeLog packages/io/can/current/cdl/io_can.cdl packages/io/can/current/doc/can_driver_doc.html packages/io/can/current/include/can.h packages/io/can/current/include/canio.h packages/io/can/current/src/can.c packages/io/common/current/include/config_keys.h
diffstat 24 files changed, 6510 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/packages/devs/can/loop/current/ChangeLog
@@ -0,0 +1,38 @@
+2005-08-15  Uwe Kindler  <uwe_kindler@web.de>
+
+	* Loopback CAN driver created
+
+//===========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
new file mode 100644
--- /dev/null
+++ b/packages/devs/can/loop/current/cdl/can_loop.cdl
@@ -0,0 +1,160 @@
+# ====================================================================
+#
+#      can_loop.cdl
+#
+#      eCos CAN LOOP configuration data
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+##
+## eCos is free software; you can redistribute it and/or modify it under
+## the terms of the GNU General Public License as published by the Free
+## Software Foundation; either version 2 or (at your option) any later version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+## WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License along
+## with eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+## at http://sources.redhat.com/ecos/ecos-license/
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):      Uwe Kindler
+# Original data:  gthomas
+# Contributors:
+# Date:           2005-07-11
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_IO_CAN_LOOP {
+    display       "Loop CAN device drivers"
+
+    parent        CYGPKG_IO_CAN_DEVICES
+    active_if     CYGPKG_IO_CAN
+    requires      CYGPKG_ERROR
+    include_dir   cyg/io
+    include_files ; # none _exported_ whatsoever
+
+    description   "
+       This package contains the loop CAN device driver."
+
+    compile       -library=libextras.a loop_can.c
+
+    # Support up to two CAN loop device.
+    for { set ::loopcan 0 } { $::loopcan < 2 } { incr ::loopcan } {
+    
+    cdl_component CYGPKG_IO_CAN_LOOP_CAN[set ::loopcan] {
+        display       "LOOP CAN channel [set ::loopcan] driver"
+        flavor        bool
+        default_value 0
+        implements    CYGINT_IO_CAN_TIMESTAMP
+        description   "
+            This option includes the CAN loop device driver for channel [set ::loopcan]." 
+    
+        cdl_option CYGDAT_DEVS_CAN_LOOP_CAN[set ::loopcan]_NAME {
+            display       "Device name for LOOP CAN channel [set ::loopcan]"
+            flavor        data
+            default_value [format {"\"/dev/can%d\""} $::loopcan]
+            description   "
+                This option specifies the device name for loop CAN channel [set ::loopcan]."
+        }
+    
+        cdl_option CYGNUM_DEVS_CAN_LOOP_CAN[set ::loopcan]_KBAUD {
+            display       "Baud rate for the LOOP CAN channel [set ::loopcan] driver"
+            flavor        data
+            default_value   100
+                legal_values    { 10 20 50 100 125 250 500 800 1000 }
+                description "This option determines the initial baud rate in KBaud for 
+                             loop CAN channel [set ::loopcan]."
+        }
+        
+        cdl_option CYGNUM_DEVS_CAN_LOOP_CAN[set ::loopcan]_QUEUESIZE_TX {
+                display     "Size of TX Queue for loop CAN channel [set ::loopcan]"
+                flavor      data
+                default_value   32
+                legal_values    16 to 512
+                description "
+                    The CAN device driver will run in interrupt mode and will
+                    perform buffering of outgoing data. This option controls the number
+                    of CAN messages the TX queue can store."
+            }
+            
+            cdl_option CYGNUM_DEVS_CAN_LOOP_CAN[set ::loopcan]_QUEUESIZE_RX {
+                display     "Size of RX Queue for the loop CAN channel [set ::loopcan]"
+                flavor      data
+                default_value   32
+                legal_values    16 to 512
+                description "
+                    The CAN device driver will run in interrupt mode and will
+                    perform buffering of incoming data. This option controls the number
+                    of CAN events the RX queue can store."
+            }
+        }
+    }
+    
+
+    cdl_component CYGPKG_IO_CAN_LOOP_OPTIONS {
+        display "CAN device driver build options"
+        flavor  none
+        description   "
+	    Package specific build options including control over
+	    compiler flags used only in building this package,
+	    and details of which tests are built."
+
+
+        cdl_option CYGPKG_IO_CAN_LOOP_CFLAGS_ADD {
+            display "Additional compiler flags"
+            flavor  data
+            no_define
+            default_value { "" }
+            description   "
+                This option modifies the set of compiler flags for
+                building these CAN device drivers. These flags
+                are used in addition to the set of global flags."
+        }
+
+        cdl_option CYGPKG_IO_CAN_LOOP_CFLAGS_REMOVE {
+            display "Suppressed compiler flags"
+            flavor  data
+            no_define
+            default_value { "" }
+            description   "
+                This option modifies the set of compiler flags for
+                building these CAN device drivers. These flags are
+                removed from the set of global flags if present."
+        }
+        
+        cdl_option CYGPKG_IO_CAN_LOOP_TESTS {
+            display "CAN loop device driver tests"
+            flavor  data
+            calculated { "tests/can_rdwr tests/can_timeout tests/can_txevent tests/can_overrun1 tests/can_overrun2 tests/can_nonblock"}         
+            description   "
+                This option specifies the set of tests for the CAN loop device drivers."
+        }
+    }
+}
+
+# EOF can_loop.cdl
new file mode 100644
--- /dev/null
+++ b/packages/devs/can/loop/current/src/loop_can.c
@@ -0,0 +1,394 @@
+//==========================================================================
+//
+//      loop_can.c
+//
+//      Loopback CAN device driver
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):   Uwe Kindler
+// Contributors: Uwe Kindler
+// Date:        2005-07-10
+// Purpose:     Loopback CAN device driver
+// Description: This device driver implements a pair of CAN lines that are
+//              connected back-to-back. Data output to one will appear as
+//              input on the other. This process in part driven by an alarm
+//              object which provides a degree of separation between the two
+//              channels.
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/hal.h>
+#include <pkgconf/io_can.h>
+#include <pkgconf/io_can_loop.h>
+#include <cyg/hal/hal_io.h>
+
+#include <cyg/io/io.h>
+#include <cyg/io/devtab.h>
+#include <cyg/io/can.h>
+#include <cyg/hal/hal_intr.h>
+#include <cyg/kernel/kapi.h>
+
+#ifdef CYGPKG_IO_CAN_LOOP
+
+//-------------------------------------------------------------------------
+
+extern void diag_printf(const char *fmt, ...);
+
+//-------------------------------------------------------------------------
+// Forward definitions
+
+static bool loop_can_init(struct cyg_devtab_entry *devtab_entry);
+static bool loop_can_putmsg(can_channel *priv, cyg_can_message *pmsg, void *pdata);
+static Cyg_ErrNo loop_can_lookup(struct cyg_devtab_entry **tab, 
+                                   struct cyg_devtab_entry *sub_tab,
+                                   const char *name);
+static bool loop_can_getevent(can_channel *priv, cyg_can_event *pevent, void *pdata);
+static Cyg_ErrNo loop_can_set_config(can_channel *chan, cyg_uint32 key,
+                                     const void *xbuf, cyg_uint32 *len);
+static void loop_can_start_xmit(can_channel *chan);
+static void loop_can_stop_xmit(can_channel *chan);
+
+static void alarm_handler(cyg_handle_t alarm, cyg_addrword_t data);
+
+
+//-------------------------------------------------------------------------
+// Alarm object for feeding data back into CAN channels
+
+static cyg_alarm alarm_obj;
+
+static cyg_handle_t alarm_handle;
+
+//-------------------------------------------------------------------------
+// Transfer FIFOs
+
+#define FIFO_SIZE 16
+
+struct fifo
+{
+    cyg_bool                tx_enable;
+    volatile int            head;
+    volatile int            tail;
+    volatile int            num;
+    volatile cyg_can_event  buf[FIFO_SIZE+1];
+};
+
+static struct fifo fifo0 = { false, 0, 0, 0 };   // from CAN0 to CAN1
+static struct fifo fifo1 = { false, 0, 0, 0 };   // from CAN1 to CAN0
+
+//-------------------------------------------------------------------------
+
+#define BUFSIZE 128
+
+//-------------------------------------------------------------------------
+// Info for each serial device controlled
+
+typedef struct loop_can_info {
+    struct fifo         *write_fifo;
+    struct fifo         *read_fifo;
+} loop_can_info;
+
+//-------------------------------------------------------------------------
+// Callback functions exported by this driver   
+CAN_LOWLEVEL_FUNS(loop_can_lowlevel_funs,
+                  loop_can_putmsg,
+                  loop_can_getevent,
+                  loop_can_set_config,
+                  loop_can_start_xmit,
+                  loop_can_stop_xmit
+     );
+
+//-------------------------------------------------------------------------
+// Hardware info for each serial line
+
+#ifdef CYGPKG_IO_CAN_LOOP_CAN0
+static loop_can_info loop_can_info0 = {
+    &fifo0,
+    &fifo1
+};
+
+static cyg_can_message  loop_can_txbuf0[CYGNUM_DEVS_CAN_LOOP_CAN0_QUEUESIZE_TX];
+static cyg_can_event    loop_can_rxbuf0[CYGNUM_DEVS_CAN_LOOP_CAN0_QUEUESIZE_RX];
+#endif // CYGPKG_IO_SERIAL_LOOP_SERIAL0
+
+#ifdef CYGPKG_IO_CAN_LOOP_CAN1
+static loop_can_info loop_can_info1 = {
+    &fifo1,
+    &fifo0
+};
+
+static cyg_can_message  loop_can_txbuf1[CYGNUM_DEVS_CAN_LOOP_CAN1_QUEUESIZE_TX];
+static cyg_can_event    loop_can_rxbuf1[CYGNUM_DEVS_CAN_LOOP_CAN1_QUEUESIZE_RX];
+#endif // CYGPKG_IO_SERIAL_LOOP_SERIAL1
+
+
+
+//-------------------------------------------------------------------------
+// Channel descriptions:
+//
+#ifdef CYGPKG_IO_CAN_LOOP_CAN0
+CAN_CHANNEL_USING_INTERRUPTS(loop_can0_chan,
+                             loop_can_lowlevel_funs,
+                             loop_can_info0,
+                             CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_LOOP_CAN0_KBAUD),
+                             loop_can_txbuf0, CYGNUM_DEVS_CAN_LOOP_CAN0_QUEUESIZE_TX,
+                             loop_can_rxbuf0, CYGNUM_DEVS_CAN_LOOP_CAN0_QUEUESIZE_RX
+    );
+#endif // CYGPKG_IO_CAN_LOOP_CAN1
+    
+#ifdef CYGPKG_IO_CAN_LOOP_CAN1
+CAN_CHANNEL_USING_INTERRUPTS(loop_can1_chan,
+                             loop_can_lowlevel_funs,
+                             loop_can_info1,
+                             CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_LOOP_CAN1_KBAUD),
+                             loop_can_txbuf1, CYGNUM_DEVS_CAN_LOOP_CAN1_QUEUESIZE_TX,
+                             loop_can_rxbuf1, CYGNUM_DEVS_CAN_LOOP_CAN1_QUEUESIZE_RX
+    );
+#endif // CYGPKG_IO_CAN_LOOP_CAN1
+ 
+ 
+  
+//-------------------------------------------------------------------------
+// And finally, the device table entries:
+//
+#ifdef CYGPKG_IO_CAN_LOOP_CAN0
+DEVTAB_ENTRY(loop_can_io0, 
+             CYGDAT_DEVS_CAN_LOOP_CAN0_NAME,
+             0,                     // Does not depend on a lower level interface
+             &cyg_io_can_devio, 
+             loop_can_init, 
+             loop_can_lookup,        // CAN driver may need initializing
+             &loop_can0_chan
+    );
+#endif // CYGPKG_IO_CAN_LOOP_CAN0
+
+#ifdef CYGPKG_IO_CAN_LOOP_CAN1
+DEVTAB_ENTRY(loop_can_io1, 
+             CYGDAT_DEVS_CAN_LOOP_CAN1_NAME,
+             0,                     // Does not depend on a lower level interface
+             &cyg_io_can_devio, 
+             loop_can_init, 
+             loop_can_lookup,        // CAN driver may need initializing
+             &loop_can1_chan
+    );
+#endif // CYGPKG_IO_CAN_LOOP_CAN1
+
+//-------------------------------------------------------------------------
+
+static bool
+loop_can_config_channel(can_channel *chan, cyg_can_info_t *new_config, bool init)
+{
+    if (new_config != &chan->config) {
+        chan->config = *new_config;
+    }
+    return true;
+}
+
+//-------------------------------------------------------------------------
+// Function to initialize the device.  Called at bootstrap time.
+
+bool loop_can_init(struct cyg_devtab_entry *tab)
+{
+    can_channel *chan = (can_channel *)tab->priv;
+
+    (chan->callbacks->can_init)(chan);
+    
+    // Set up alarm for feeding data back into channels
+
+    cyg_alarm_create( cyg_real_time_clock(),
+                      alarm_handler,
+                      0,
+                      &alarm_handle,
+                      &alarm_obj);
+
+    cyg_alarm_initialize( alarm_handle, 1, 1 );
+    
+    loop_can_config_channel(chan, &chan->config, true);
+    
+    return true;
+}
+
+//-------------------------------------------------------------------------
+// This routine is called when the device is "looked" up (i.e. attached)
+
+static Cyg_ErrNo 
+loop_can_lookup(struct cyg_devtab_entry **tab, 
+                struct cyg_devtab_entry *sub_tab,
+                const char *name)
+{
+    can_channel *chan = (can_channel *)(*tab)->priv;
+    (chan->callbacks->can_init)(chan);
+    return ENOERR;
+}
+
+//-------------------------------------------------------------------------
+// Return 'true' if message is sent to device
+
+bool
+loop_can_putmsg(can_channel *chan, cyg_can_message *pmsg, void *pdata)
+{
+    loop_can_info *loop_chan = (loop_can_info *)chan->dev_priv;
+
+    struct fifo *fwr = loop_chan->write_fifo;
+    struct fifo *frd = loop_chan->read_fifo;
+
+    if( fwr->num == FIFO_SIZE )
+    {
+        return false;
+    }
+
+    fwr->buf[fwr->tail].msg  = *pmsg;
+    fwr->buf[fwr->tail].flags = CYGNUM_CAN_EVENT_RX;
+    fwr->num++;
+    fwr->tail = (fwr->tail + 1) % FIFO_SIZE;
+    
+#ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT 
+    //
+    // if TX events are supported we insert a TX event into read fifo
+    //
+    if( frd->num < FIFO_SIZE )
+    {
+        frd->buf[frd->tail].msg  = *pmsg;
+        frd->buf[frd->tail].flags = CYGNUM_CAN_EVENT_TX;
+        frd->num++;
+        frd->tail = (frd->tail + 1) % FIFO_SIZE;
+    }   
+#endif
+    
+    return true;
+}
+
+//-------------------------------------------------------------------------
+
+bool loop_can_getevent(can_channel *chan, cyg_can_event *pevent, void *pdata)
+{
+    loop_can_info *loop_chan = (loop_can_info *)chan->dev_priv;
+
+    struct fifo *frd = loop_chan->read_fifo;
+    
+    while( frd->num == 0 )
+    {
+        continue;
+    }
+
+    *pevent = frd->buf[frd->head];
+    
+    
+#ifdef CYGOPT_IO_CAN_SUPPORT_TIMESTAMP 
+    //
+    // if timestamps are supported then we store a actual timestamp into
+    // CAN event
+    // 
+    pevent->timestamp = cyg_current_time();
+#endif // CYGOPT_IO_CAN_SUPPORT_TIMESTAMP
+
+    frd->num--;
+    frd->head = (frd->head + 1) % FIFO_SIZE;
+    
+    return true;
+}
+
+//-------------------------------------------------------------------------
+
+static Cyg_ErrNo
+loop_can_set_config(can_channel *chan, cyg_uint32 key,
+                    const void *xbuf, cyg_uint32 *len)
+{
+    return ENOERR;
+}
+
+
+//-------------------------------------------------------------------------
+// Enable the transmitter on the device
+
+static void
+loop_can_start_xmit(can_channel *chan)
+{  
+    loop_can_info *loop_chan = (loop_can_info *)chan->dev_priv;
+
+    loop_chan->write_fifo->tx_enable = true;
+    
+    (chan->callbacks->xmt_msg)(chan, 0);  
+}
+
+//-------------------------------------------------------------------------
+// Disable the transmitter on the device
+
+static void 
+loop_can_stop_xmit(can_channel *chan)
+{ 
+    loop_can_info *loop_chan = (loop_can_info *)chan->dev_priv;
+
+    loop_chan->write_fifo->tx_enable = false;  
+}
+
+//-------------------------------------------------------------------------
+
+static void alarm_handler(cyg_handle_t alarm, cyg_addrword_t data)
+{
+    can_channel *chan0 = &loop_can0_chan;
+    can_channel *chan1 = &loop_can1_chan;
+
+
+    while(fifo0.num )
+    {
+        (chan1->callbacks->rcv_event)(chan1, 0);
+        
+        if(fifo0.tx_enable )
+        {
+            (chan0->callbacks->xmt_msg)(chan0, 0); 
+        }       
+    }
+
+    while(fifo1.num )
+    {
+        (chan0->callbacks->rcv_event)(chan0, 0);
+        
+        if(fifo1.tx_enable )
+        {
+            (chan1->callbacks->xmt_msg)(chan1, 0); 
+        }        
+    } // while( fifo1.num )
+}
+    
+
+#endif // CYGPKG_IO_CAN_LOOP
+
+//-------------------------------------------------------------------------
+// EOF loop_can.c
new file mode 100644
--- /dev/null
+++ b/packages/devs/can/loop/current/tests/can_nonblock.c
@@ -0,0 +1,196 @@
+//==========================================================================
+//
+//        flexcan_load.c
+//
+//        FlexCAN load test
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     Uwe Kindler
+// Contributors:  Uwe Kindler
+// Date:          2005-08-14
+// Description:   FlexCAN load test
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+//                                INCLUDES
+//===========================================================================
+#include <pkgconf/system.h>
+
+#include <cyg/infra/testcase.h>         // test macros
+#include <cyg/infra/cyg_ass.h>          // assertion macros
+#include <cyg/infra/diag.h>
+
+// Package requirements
+#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL)
+
+#include <pkgconf/kernel.h>
+#include <cyg/io/io.h>
+#include <cyg/io/canio.h>
+
+// Package option requirements
+#if defined(CYGFUN_KERNEL_API_C)
+
+#include <cyg/hal/hal_arch.h>           // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/kernel/kapi.h>
+
+// Package option requirements
+#if defined(CYGOPT_IO_CAN_SUPPORT_NONBLOCKING) && !defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS)
+
+//===========================================================================
+//                               DATA TYPES
+//===========================================================================
+typedef struct st_thread_data
+{
+    cyg_thread   obj;
+    long         stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+    cyg_handle_t hdl;
+} thread_data_t;
+
+
+//===========================================================================
+//                              LOCAL DATA
+//===========================================================================
+cyg_thread_entry_t can0_thread;
+thread_data_t      can0_thread_data;
+
+
+cyg_io_handle_t    hDrvFlexCAN;
+
+
+//===========================================================================
+//                          LOCAL FUNCTIONS
+//===========================================================================
+#include "can_test_aux.inl" // include CAN test auxiliary functions
+
+
+//===========================================================================
+//                             READER THREAD 
+//===========================================================================
+void can0_thread(cyg_addrword_t data)
+{
+    cyg_uint32             len;
+    cyg_uint32             blocking;
+    cyg_can_event          rx_event;
+
+    blocking = 0;
+    len = sizeof(blocking);
+    if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_READ_BLOCKING ,&blocking, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0");
+    } 
+    
+    len = sizeof(rx_event); 
+            
+    if (-EAGAIN == cyg_io_read(hDrvFlexCAN, &rx_event, &len))
+    {
+        CYG_TEST_PASS_FINISH("can_test1 test OK");
+    }
+    else
+    {
+        CYG_TEST_FAIL_FINISH("Error reading from /dev/can0");
+    }           
+}
+
+
+void
+cyg_start(void)
+{
+    cyg_uint32     len;
+    cyg_can_info_t can_cfg;
+    
+    CYG_TEST_INIT();
+    
+    //
+    // open flexcan device driver
+    //
+    if (ENOERR != cyg_io_lookup("/dev/can0", &hDrvFlexCAN)) 
+    {
+        CYG_TEST_FAIL_FINISH("Error opening /dev/can0");
+    }
+    
+    //
+    // setup CAN baudrate 250 KBaud
+    //
+    can_cfg.baud = CYGNUM_CAN_KBAUD_250;
+    len = sizeof(can_cfg);
+    if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_INFO ,&can_cfg, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0");
+    }
+    
+    //
+    // create the two threads which access the CAN device driver
+    // a reader thread with a higher priority and a writer thread
+    // with a lower priority
+    //
+    cyg_thread_create(4, can0_thread, 
+                        (cyg_addrword_t) 0,
+		                "can0_thread", 
+		                (void *) can0_thread_data.stack, 
+		                1024 * sizeof(long),
+		                &can0_thread_data.hdl, 
+		                &can0_thread_data.obj);
+		                
+    cyg_thread_resume(can0_thread_data.hdl);
+    
+    cyg_scheduler_start();
+}
+
+#else // #if defined(CYGOPT_IO_CAN_SUPPORT_NONBLOCKING) && !defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
+#define N_A_MSG "Needs nonblocking calls and disabled timeouts"
+#endif
+
+#else // CYGFUN_KERNEL_API_C
+#define N_A_MSG "Needs kernel C API"
+#endif
+
+#else // CYGPKG_IO_CAN && CYGPKG_KERNEL
+#define N_A_MSG "Needs IO/CAN and Kernel"
+#endif
+
+#ifdef N_A_MSG
+void
+cyg_start( void )
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA( N_A_MSG);
+}
+#endif // N_A_MSG
+
+// EOF flexcan_load.c
new file mode 100644
--- /dev/null
+++ b/packages/devs/can/loop/current/tests/can_overrun1.c
@@ -0,0 +1,268 @@
+//==========================================================================
+//
+//        can_overrun1.c
+//
+//        Test CAN device drivers
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     Uwe Kindler
+// Contributors:  Uwe Kindler
+// Date:          2005-08-07
+// Description:   Simple read/write test of CAN driver
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+//                                INCLUDES
+//===========================================================================
+#include <pkgconf/system.h>
+
+#include <cyg/infra/testcase.h>         // test macros
+#include <cyg/infra/cyg_ass.h>          // assertion macros
+#include <cyg/infra/diag.h>
+
+// Package requirements
+#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL)
+
+#include <pkgconf/kernel.h>
+#include <cyg/io/io.h>
+#include <cyg/io/canio.h>
+
+// Package option requirements
+#if defined(CYGFUN_KERNEL_API_C)
+
+#include <cyg/hal/hal_arch.h>           // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/kernel/kapi.h>
+
+// tx event support required
+#if defined(CYGOPT_IO_CAN_TX_EVENT_SUPPORT)
+
+
+//===========================================================================
+//                               DATA TYPES
+//===========================================================================
+typedef struct st_thread_data
+{
+    cyg_thread   obj;
+    long         stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+    cyg_handle_t hdl;
+} thread_data_t;
+
+
+//===========================================================================
+//                              LOCAL DATA
+//===========================================================================
+cyg_thread_entry_t can0_thread;
+thread_data_t      can0_thread_data;
+
+
+//===========================================================================
+//                          LOCAL FUNCTIONS
+//===========================================================================
+#include "can_test_aux.inl" // include CAN test auxiliary functions
+
+
+//===========================================================================
+//                             WRITER THREAD 
+//===========================================================================
+void can0_thread(cyg_addrword_t data)
+{
+    cyg_io_handle_t    hCAN0;
+    cyg_uint8          i;
+    cyg_uint32         len;
+    cyg_can_buf_info_t buf_info;
+    cyg_can_event      rx_event;
+    cyg_can_message    tx_msg =
+    {
+        0x000,                                               // CAN identifier
+        {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7},    // 8 data bytes
+        CYGNUM_CAN_ID_STD,                                   // standard frame
+        CYGNUM_CAN_FRAME_DATA,                               // data frame
+        0,                                                   // data length code
+    };
+    
+    if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0)) 
+    {
+        CYG_TEST_FAIL_FINISH("Error opening /dev/can0");
+    }
+    
+    len = sizeof(buf_info);
+    if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&buf_info, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0");
+    }
+    
+    if (buf_info.rx_count > 0)
+    {
+        CYG_TEST_FAIL_FINISH("Empty RX buffer expected for /dev/can0");
+    }
+    
+    //
+    // now we send exactly one CAN message more than it is space in left in buffer
+    // Because each TX message will cause a TX event in receive queue we should
+    // get a RX queue overrun
+    //
+    diag_printf("Sending %d CAN messages to /dev/can0\n", buf_info.rx_bufsize + 1);
+    for (i = 0; i <= buf_info.rx_bufsize; ++i)
+    {
+        tx_msg.id = 0x000 + i;
+        tx_msg.data[0] = i;
+        len = sizeof(tx_msg);
+        
+        if (ENOERR != cyg_io_write(hCAN0, &tx_msg, &len))
+        {
+            CYG_TEST_FAIL_FINISH("Error writing to /dev/can0");
+        }
+        else
+        {
+            print_can_msg(&tx_msg, "");
+        } 
+    }
+    
+    //
+    // now check if receive queue is completely filled - that means number of rx events should
+    // be equal to RX queue size
+    //
+    if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&buf_info, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0");
+    }
+    
+    if (buf_info.rx_bufsize != buf_info.rx_count)
+    {
+        CYG_TEST_FAIL_FINISH("Number of events in /dev/can0 RX queue differs from queue size");
+    }
+    
+    //
+    // Now read all events from receive queue - if everything is o.k. than the oldest
+    // event should be overwritten by the latest sent message and the last event in
+    // queue should indicate a RX overrun
+    //
+    diag_printf("\nReceiving %d CAN messages from /dev/can0\n", buf_info.rx_bufsize);
+    for (i = 0; i < buf_info.rx_bufsize; ++i)
+    {
+        len = sizeof(rx_event);
+        
+        if (ENOERR != cyg_io_read(hCAN0, &rx_event, &len))
+        {
+            CYG_TEST_FAIL_FINISH("Error reading from /dev/can1");
+        } 
+        else
+        {
+            //
+            // if we received a valid TX event then we can print the message
+            //
+            if (rx_event.flags & CYGNUM_CAN_EVENT_TX)
+            {
+                print_can_msg(&rx_event.msg, "");
+                if (rx_event.msg.data[0] != (i + 1))
+                {
+                    CYG_TEST_FAIL_FINISH("Received /dev/can0 TX event contains invalid data");
+                }                    
+            }
+            else
+            {
+                CYG_TEST_FAIL_FINISH("Unexpected CAN event for /dev/can0");
+            }
+            
+            //
+            // now check if any other flag is set
+            //
+            if (rx_event.flags &  CYGNUM_CAN_EVENT_OVERRUN_RX)
+            {
+                diag_printf("RX queue overrun successfully indicated for /dev/can0\n");
+                if (i < (buf_info.rx_bufsize - 1))
+                {
+                    CYG_TEST_FAIL_FINISH("RX queue overrun occured too early /dev/can0");
+                }
+                else
+                {
+                    CYG_TEST_PASS_FINISH("can_overrun1 test OK"); 
+                }
+            } // if (rx_event.flags &  CYGNUM_CAN_EVENT_OVERRUN_RX)         
+        }   
+    } // for (i = 0; i < buf_info.rx_bufsize; ++i)
+    
+    CYG_TEST_FAIL_FINISH("RX overrun expected but not received for /dev/can0");
+}
+
+
+
+void
+cyg_start(void)
+{
+    CYG_TEST_INIT();
+    
+    //
+    // create the two threads which access the CAN device driver
+    //
+    cyg_thread_create(4, can0_thread, 
+                        (cyg_addrword_t) 0,
+		                "can0_thread", 
+		                (void *) can0_thread_data.stack, 
+		                1024 * sizeof(long),
+		                &can0_thread_data.hdl, 
+		                &can0_thread_data.obj);
+		                
+    cyg_thread_resume(can0_thread_data.hdl);
+    
+    cyg_scheduler_start();
+}
+
+#else // CYGOPT_IO_CAN_TX_EVENT_SUPPORT
+#define N_A_MSG "TX event support required for IO/CAN"
+#endif
+
+#else // CYGFUN_KERNEL_API_C
+#define N_A_MSG "Needs kernel C API"
+#endif
+
+#else // CYGPKG_IO_CAN && CYGPKG_KERNEL
+#define N_A_MSG "Needs IO/CAN and Kernel"
+#endif
+
+#ifdef N_A_MSG
+void
+cyg_start( void )
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA( N_A_MSG);
+}
+#endif // N_A_MSG
+
+// EOF serial4.c
new file mode 100644
--- /dev/null
+++ b/packages/devs/can/loop/current/tests/can_overrun2.c
@@ -0,0 +1,352 @@
+//==========================================================================
+//
+//        can_overrun2.c
+//
+//        Test CAN device RX overrun events
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     Uwe Kindler
+// Contributors:  Uwe Kindler
+// Date:          2005-08-07
+// Description:   Simple read/write test of CAN driver
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+//                                INCLUDES
+//===========================================================================
+#include <pkgconf/system.h>
+
+#include <cyg/infra/testcase.h>         // test macros
+#include <cyg/infra/cyg_ass.h>          // assertion macros
+#include <cyg/infra/diag.h>
+
+// Package requirements
+#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL)
+
+#include <pkgconf/kernel.h>
+#include <cyg/io/io.h>
+#include <cyg/io/canio.h>
+
+// Package option requirements
+#if defined(CYGFUN_KERNEL_API_C)
+
+#include <cyg/hal/hal_arch.h>           // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/kernel/kapi.h>
+
+
+//===========================================================================
+//                               DATA TYPES
+//===========================================================================
+typedef struct st_thread_data
+{
+    cyg_thread   obj;
+    long         stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+    cyg_handle_t hdl;
+} thread_data_t;
+
+
+//===========================================================================
+//                              LOCAL DATA
+//===========================================================================
+cyg_thread_entry_t can0_thread;
+thread_data_t      can0_thread_data;
+
+cyg_thread_entry_t can1_thread;
+thread_data_t      can1_thread_data;
+
+
+//===========================================================================
+//                          LOCAL FUNCTIONS
+//===========================================================================
+#include "can_test_aux.inl" // include CAN test auxiliary functions
+
+
+//===========================================================================
+//                             WRITER THREAD 
+//===========================================================================
+void can0_thread(cyg_addrword_t data)
+{
+    cyg_io_handle_t    hCAN0;
+    cyg_uint8          i;
+    cyg_uint32         len;
+    cyg_uint32         rx_bufsize;
+    cyg_can_buf_info_t tx_buf_info;
+    cyg_can_event      rx_event;
+    cyg_can_message    tx_msg =
+    {
+        0x000,                                               // CAN identifier
+        {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7},    // 8 data bytes
+        CYGNUM_CAN_ID_STD,                                   // standard frame
+        CYGNUM_CAN_FRAME_DATA,                               // data frame
+        2,                                                   // data length code
+    };
+    
+    if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0)) 
+    {
+        CYG_TEST_FAIL_FINISH("Error opening /dev/can0");
+    }
+    
+    len = sizeof(tx_buf_info);
+    if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&tx_buf_info, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0");
+    }
+    
+    //
+    // Before we can write the CAN messages, we need to know the buffer size of the
+    // receiver. The receiver will tell us this buffer size with one single CAN
+    // message
+    //
+    len = sizeof(rx_event); 
+            
+    if (ENOERR != cyg_io_read(hCAN0, &rx_event, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error reading from /dev/can0");
+    }
+    
+    //
+    // we expect a RX event here - we treat any other flag as an error
+    //
+    if (!(rx_event.flags & CYGNUM_CAN_EVENT_RX) || (rx_event.flags & !CYGNUM_CAN_EVENT_RX))
+    {
+        CYG_TEST_FAIL_FINISH("Unexpected RX event for /dev/can0");
+    }
+    
+    rx_bufsize = *((cyg_uint32 *)rx_event.msg.data);
+    
+    //
+    // now we send exactly one CAN message more than there is space in the receive buffer
+    // this should cause an RX ovverun in receive buffer
+    //
+    diag_printf("/dev/can0: Sending %d CAN messages\n", rx_bufsize); 
+    for (i = 0; i <= rx_bufsize; ++i)
+    {
+        //
+        // we store the message number as CAN id and in first data byte so
+        // a receiver can check this later
+        //
+        tx_msg.id = 0x000 + i;
+        tx_msg.data[0] = i;
+        len = sizeof(tx_msg); 
+            
+        if (ENOERR != cyg_io_write(hCAN0, &tx_msg, &len))
+        {
+            CYG_TEST_FAIL_FINISH("Error writing to /dev/can0");
+        }
+        else
+        {
+            print_can_msg(&tx_msg, "");
+        }
+    }  // for (i = 0; i <= rx_bufsize; ++i)
+    
+    cyg_thread_suspend(cyg_thread_self());                 
+}
+
+
+//===========================================================================
+//                            READER THREAD
+//===========================================================================
+void can1_thread(cyg_addrword_t data)
+{
+    cyg_io_handle_t    hCAN1;
+    cyg_uint8          i;
+    cyg_uint32         len;
+    cyg_can_buf_info_t rx_buf_info;
+    cyg_can_event      rx_event;
+    cyg_can_message    tx_msg;
+    
+    if (ENOERR != cyg_io_lookup("/dev/can1", &hCAN1)) 
+    {
+        CYG_TEST_FAIL_FINISH("Error opening /dev/can1");
+    }
+    
+    len = sizeof(rx_buf_info);
+    if (ENOERR != cyg_io_get_config(hCAN1, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&rx_buf_info, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error reading config of /dev/can1");
+    }
+    
+    //
+    // first we send the size of our receive buffer to the writer
+    // we setup tx message now
+    //
+    tx_msg.id  = 0x000;
+    tx_msg.ext = CYGNUM_CAN_ID_STD;
+    tx_msg.rtr = CYGNUM_CAN_FRAME_DATA;
+    tx_msg.dlc = sizeof(rx_buf_info.rx_bufsize);
+    
+    //
+    // we store size of rx buffer in CAN message. We do not need to care about
+    // endianess here because this is a loopback driver test and we will receive
+    // our own messages
+    //
+    *((cyg_uint32 *)tx_msg.data) = rx_buf_info.rx_bufsize;
+    len = sizeof(tx_msg); 
+    
+    //
+    // as soon as we send a CAN message, thread 0 will resume because it is waiting
+    // for a message
+    //
+    diag_printf("/dev/can1: Sending size of RX buffer %d\n", rx_buf_info.rx_bufsize);        
+    if (ENOERR != cyg_io_write(hCAN1, &tx_msg, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error writing to /dev/can1");
+    }
+    cyg_thread_delay(10); // let thread 0 run
+       
+    //
+    // now we check if we received CAN messages  - if receive buffer is not full
+    // the we have an error here because we expect a full receive buffer
+    //
+    len = sizeof(rx_buf_info);
+    if (ENOERR != cyg_io_get_config(hCAN1, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&rx_buf_info, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error reading config of /dev/can1");
+    }
+    
+    if (rx_buf_info.rx_bufsize != rx_buf_info.rx_count)
+    {
+        CYG_TEST_FAIL_FINISH("RX buffer of /dev/can1 does not contain number of expected messages");
+    }
+    
+    //
+    // now we wait for messages from /dev/can0
+    //
+    diag_printf("/dev/can1: Receiving %d CAN messages\n", rx_buf_info.rx_count);
+    for (i = 0; i < rx_buf_info.rx_count; ++i)
+    {
+        len = sizeof(rx_event);
+        if (ENOERR != cyg_io_read(hCAN1, &rx_event, &len))
+        {
+            CYG_TEST_FAIL_FINISH("Error reading from /dev/can0");
+        }
+        else
+        {
+            if (rx_event.flags & CYGNUM_CAN_EVENT_RX)
+            {
+                print_can_msg(&rx_event.msg, "");
+                if (rx_event.msg.data[0] != (i + 1))
+                {
+                    CYG_TEST_FAIL_FINISH("Received /dev/can1 RX event contains invalid data");
+                }                    
+            }
+            else
+            {
+                CYG_TEST_FAIL_FINISH("Unexpected CAN event for /dev/can1");
+            }
+            
+            //
+            // now check if any other flag is set
+            //
+            if (rx_event.flags &  CYGNUM_CAN_EVENT_OVERRUN_RX)
+            {
+                diag_printf("RX queue overrun successfully indicated for /dev/can1\n");
+
+//
+// if TX events are supported then we have already a TX event in receive queue because
+// we sent a message and the RX queue overrun will occur one message earlier
+//
+#if defined(CYGOPT_IO_CAN_TX_EVENT_SUPPORT)
+                if (i < (rx_buf_info.rx_bufsize - 2))
+#else
+                if (i < (rx_buf_info.rx_bufsize - 1))
+#endif
+                {
+                    CYG_TEST_FAIL_FINISH("RX queue overrun occured too early for /dev/can1");
+                }
+                else
+                {
+                    CYG_TEST_PASS_FINISH("can_overrun2 test OK"); 
+                }
+            } // if (rx_event.flags &  CYGNUM_CAN_EVENT_OVERRUN_RX)  
+        }
+        
+    }
+}
+
+
+
+void
+cyg_start(void)
+{
+    CYG_TEST_INIT();
+    
+    //
+    // create the two threads which access the CAN device driver
+    //
+    cyg_thread_create(4, can0_thread, 
+                        (cyg_addrword_t) 0,
+		                "can0_thread", 
+		                (void *) can0_thread_data.stack, 
+		                1024 * sizeof(long),
+		                &can0_thread_data.hdl, 
+		                &can0_thread_data.obj);
+		                
+    cyg_thread_create(5, can1_thread, 
+                        (cyg_addrword_t) can0_thread_data.hdl,
+		                "can1_thread", 
+		                (void *) can1_thread_data.stack, 
+		                1024 * sizeof(long),
+		                &can1_thread_data.hdl, 
+		                &can1_thread_data.obj);
+		                
+    cyg_thread_resume(can0_thread_data.hdl);
+    cyg_thread_resume(can1_thread_data.hdl);
+    
+    cyg_scheduler_start();
+}
+
+#else // CYGFUN_KERNEL_API_C
+#define N_A_MSG "Needs kernel C API"
+#endif
+
+#else // CYGPKG_IO_CAN && CYGPKG_KERNEL
+#define N_A_MSG "Needs IO/CAN and Kernel"
+#endif
+
+#ifdef N_A_MSG
+void
+cyg_start( void )
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA( N_A_MSG);
+}
+#endif // N_A_MSG
+
+// EOF serial4.c
new file mode 100644
--- /dev/null
+++ b/packages/devs/can/loop/current/tests/can_rdwr.c
@@ -0,0 +1,289 @@
+//==========================================================================
+//
+//        can_rdwr.c
+//
+//        Test CAN device drivers
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     Uwe Kindler
+// Contributors:  Uwe Kindler
+// Date:          2005-08-07
+// Description:   Simple read/write test of CAN driver
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+//                                INCLUDES
+//===========================================================================
+#include <pkgconf/system.h>
+
+#include <cyg/infra/testcase.h>         // test macros
+#include <cyg/infra/cyg_ass.h>          // assertion macros
+#include <cyg/infra/diag.h>
+
+// Package requirements
+#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL)
+
+#include <pkgconf/kernel.h>
+#include <cyg/io/io.h>
+#include <cyg/io/canio.h>
+
+// Package option requirements
+#if defined(CYGFUN_KERNEL_API_C)
+
+#include <cyg/hal/hal_arch.h>           // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/kernel/kapi.h>
+
+
+//===========================================================================
+//                               DATA TYPES
+//===========================================================================
+typedef struct st_thread_data
+{
+    cyg_thread   obj;
+    long         stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+    cyg_handle_t hdl;
+} thread_data_t;
+
+
+//===========================================================================
+//                              LOCAL DATA
+//===========================================================================
+cyg_thread_entry_t can0_thread;
+thread_data_t      can0_thread_data;
+
+cyg_thread_entry_t can1_thread;
+thread_data_t      can1_thread_data;
+
+
+//===========================================================================
+//                          LOCAL FUNCTIONS
+//===========================================================================
+#include "can_test_aux.inl" // include CAN test auxiliary functions
+
+
+//===========================================================================
+//                             WRITER THREAD 
+//===========================================================================
+void can0_thread(cyg_addrword_t data)
+{
+    cyg_io_handle_t    hCAN0;
+    cyg_uint8          i;
+    cyg_uint32         len;
+    cyg_can_buf_info_t tx_buf_info;
+    cyg_can_message    tx_msg =
+    {
+        0x000,                                               // CAN identifier
+        {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7},    // 8 data bytes
+        CYGNUM_CAN_ID_STD,                                   // standard frame
+        CYGNUM_CAN_FRAME_DATA,                               // data frame
+        8,                                                   // data length code
+    };
+    
+    if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0)) 
+    {
+        CYG_TEST_FAIL_FINISH("Error opening /dev/can0");
+    }
+    
+    len = sizeof(tx_buf_info);
+    if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&tx_buf_info, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0");
+    }
+    
+    if (tx_buf_info.tx_bufsize < 10)
+    {
+        CYG_TEST_FAIL_FINISH("TX quesize of /dev/can0 too small for 10 CAN messages");
+    }
+    
+    while (1)
+    {
+        //
+        // now we simply send 10 CAN messages and then suspend the thread
+        //
+        CYG_TEST_INFO("Thread0: Writing 10 CAN messages");
+        for (i = 0; i < 10; ++i)
+        {
+            //
+            // we store the message number as CAN id and in first data byte so
+            // a receiver can check this later
+            //
+            tx_msg.id = 0x000 + i;
+            tx_msg.data[0] = i;
+            len = sizeof(tx_msg); 
+            
+            if (ENOERR != cyg_io_write(hCAN0, &tx_msg, &len))
+            {
+                CYG_TEST_FAIL_FINISH("Error writing to /dev/can0");
+            }
+            else
+            {
+                print_can_msg(&tx_msg, "");
+            }
+        }
+        
+        //
+        // Now we we give the reader thread a chance to run and to read
+        // the messages      
+        //
+        cyg_thread_delay(100);
+        CYG_TEST_FAIL_FINISH("Error reading from /dev/can0");                      
+    }
+}
+
+
+//===========================================================================
+//                            READER THREAD
+//===========================================================================
+void can1_thread(cyg_addrword_t data)
+{
+    cyg_io_handle_t    hCAN1;
+    cyg_uint8          i;
+    cyg_uint32         len;
+    cyg_can_buf_info_t rx_buf_info;
+    cyg_can_event      rx_event;
+    
+    if (ENOERR != cyg_io_lookup("/dev/can1", &hCAN1)) 
+    {
+        CYG_TEST_FAIL_FINISH("Error opening /dev/can1");
+    }
+    
+    len = sizeof(rx_buf_info);
+    if (ENOERR != cyg_io_get_config(hCAN1, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&rx_buf_info, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error reading config of /dev/can1");
+    }
+    
+    if (rx_buf_info.rx_bufsize < 10)
+    {
+        CYG_TEST_FAIL_FINISH("RX quesize of /dev/can1 too small for 10 CAN events");
+    }
+    
+    while (1)
+    {
+        //
+        // now we try to read the 10 CAN messages that was sent by writer 
+        // thread previously
+        //
+        CYG_TEST_INFO("Thread1: Reading 10 CAN messages");
+        for (i = 0; i < 10; ++i)
+        {
+            len = sizeof(rx_event); 
+            
+            if (ENOERR != cyg_io_read(hCAN1, &rx_event, &len))
+            {
+                CYG_TEST_FAIL_FINISH("Error reading from /dev/can1");
+            }
+            
+            //
+            // we expect only RX events in this test case - so all other events
+            // cause a test fail
+            //
+            if (!(rx_event.flags & CYGNUM_CAN_EVENT_RX))
+            {
+                CYG_TEST_FAIL_FINISH("Received wrong CAN event type");
+            }
+            
+            //
+            // The writer thread stored the message number in CAN id and first
+            // data byte so we can check now if we received valid data
+            //
+            if ((rx_event.msg.id != i) || (rx_event.msg.data[0] != i))
+            {
+                CYG_TEST_FAIL_FINISH("Received CAN message contains unexpected data");
+            }
+            else
+            {
+                print_can_msg(&rx_event.msg, "");
+            }
+        } //for (i = 0; i < 10; ++i)
+        
+        CYG_TEST_PASS_FINISH("can_rdwr test OK");
+    } // while (1)
+}
+
+
+
+void
+cyg_start(void)
+{
+    CYG_TEST_INIT();
+    
+    //
+    // create the two threads which access the CAN device driver
+    //
+    cyg_thread_create(4, can0_thread, 
+                        (cyg_addrword_t) 0,
+		                "can0_thread", 
+		                (void *) can0_thread_data.stack, 
+		                1024 * sizeof(long),
+		                &can0_thread_data.hdl, 
+		                &can0_thread_data.obj);
+		                
+    cyg_thread_create(5, can1_thread, 
+                        (cyg_addrword_t) can0_thread_data.hdl,
+		                "can1_thread", 
+		                (void *) can1_thread_data.stack, 
+		                1024 * sizeof(long),
+		                &can1_thread_data.hdl, 
+		                &can1_thread_data.obj);
+		                
+    cyg_thread_resume(can0_thread_data.hdl);
+    cyg_thread_resume(can1_thread_data.hdl);
+    
+    cyg_scheduler_start();
+}
+
+#else // CYGFUN_KERNEL_API_C
+#define N_A_MSG "Needs kernel C API"
+#endif
+
+#else // CYGPKG_IO_CAN && CYGPKG_KERNEL
+#define N_A_MSG "Needs IO/CAN and Kernel"
+#endif
+
+#ifdef N_A_MSG
+void
+cyg_start( void )
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA( N_A_MSG);
+}
+#endif // N_A_MSG
+
+// EOF serial4.c
new file mode 100644
--- /dev/null
+++ b/packages/devs/can/loop/current/tests/can_test_aux.inl
@@ -0,0 +1,144 @@
+//==========================================================================
+//
+//        can_test_aux.inl
+//
+//        CAN test auxiliary functions
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     Uwe Kindler
+// Contributors:  Uwe Kindler
+// Date:          2005-08-07
+// Description:   Auxiliary functions for CAN driver tests
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+//                           PRINT CAN EVENT
+//===========================================================================
+void print_can_msg(cyg_can_message *pmsg, char *pMsg)
+{   
+    char *pmsg_str;
+    static char* msg_tbl[] =
+    {
+        "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:]\n",
+        "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X]\n",
+        "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X]\n",
+        "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X]\n",
+        "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X]\n",
+        "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X %02X]\n",
+        "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X %02X %02X]\n",
+        "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X %02X %02X %02X]\n",
+        "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X %02X %02X %02X %02X]\n"
+    };
+    
+    if (pmsg->rtr)
+    {
+        diag_printf("%s [ID:%03X] [RTR:%d] [EXT:%d]\n",
+                    pMsg,
+                    pmsg->id,
+                    pmsg->rtr,
+                    pmsg->ext);
+                    
+        return;
+    }
+    
+    if (pmsg->dlc > 8)
+    {
+        pmsg_str = msg_tbl[8];
+    }   
+    else
+    {
+        pmsg_str = msg_tbl[pmsg->dlc];
+    } 
+    
+    diag_printf(pmsg_str,
+                pMsg,
+                pmsg->id,
+                pmsg->rtr,
+                pmsg->ext,
+                pmsg->data[0],
+                pmsg->data[1],
+                pmsg->data[2],
+                pmsg->data[3],
+                pmsg->data[4],
+                pmsg->data[5],
+                pmsg->data[6],
+                pmsg->data[7]);
+}
+
+
+//===========================================================================
+//                         PRINT CAN EVENT FLAGS
+//===========================================================================
+void print_can_flags(cyg_uint16 flags, char *pMsg)
+{
+    char      *pmsg_str;
+    cyg_uint8  i ;
+    static char* msg_tbl[] =
+    {
+        "RX  ",
+        "TX  ",
+        "WRX  ",
+        "WTX  ",
+        "ERRP  ",
+        "BOFF  ",
+        "OVRX  ",
+        "OVTX  ",
+        "CERR  ",
+        "LSTY  ",
+        "ESTY  ",
+        "ALOS  ",
+        "DEVC  ",
+    };
+    i = 0;
+    while (flags && (i < 16))
+    {
+        if (flags & 0x0001)
+        {
+            pmsg_str = msg_tbl[i];
+            diag_printf(pmsg_str);
+        }
+        flags >>=1;
+        i++;
+    }
+    
+    diag_printf("\n");
+}
+
+//---------------------------------------------------------------------------
+// end of can_test_aux.inl
new file mode 100644
--- /dev/null
+++ b/packages/devs/can/loop/current/tests/can_timeout.c
@@ -0,0 +1,247 @@
+//==========================================================================
+//
+//        can_timeout.c
+//
+//        Test CAN device driver timeouts
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     Uwe Kindler
+// Contributors:  Uwe Kindler
+// Date:          2005-08-07
+// Description:   Timeout test of CAN device driver
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+//                                INCLUDES
+//===========================================================================
+#include <pkgconf/system.h>
+
+#include <cyg/infra/testcase.h>         // test macros
+#include <cyg/infra/cyg_ass.h>          // assertion macros
+#include <cyg/infra/diag.h>
+
+// Package requirements
+#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL)
+
+#include <pkgconf/kernel.h>
+#include <cyg/io/io.h>
+#include <cyg/io/canio.h>
+
+// Package option requirements
+#if defined(CYGFUN_KERNEL_API_C)
+
+#include <cyg/hal/hal_arch.h>           // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/kernel/kapi.h>
+
+// timeout support required
+#if defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS)
+
+
+//===========================================================================
+//                               DATA TYPES
+//===========================================================================
+typedef struct st_thread_data
+{
+    cyg_thread   obj;
+    long         stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+    cyg_handle_t hdl;
+} thread_data_t;
+
+
+//===========================================================================
+//                              LOCAL DATA
+//===========================================================================
+cyg_thread_entry_t can0_thread;
+thread_data_t      can0_thread_data;
+
+
+//===========================================================================
+//                          LOCAL FUNCTIONS
+//===========================================================================
+#include "can_test_aux.inl" // include CAN test auxiliary functions
+
+
+//===========================================================================
+// Measure timeout time and compare it with RX timeout value
+//===========================================================================
+void check_timeout(cyg_io_handle_t hCAN, cyg_uint32 timeout)
+{
+    cyg_can_event          rx_event;
+    cyg_can_timeout_info_t timeout_info;
+    cyg_uint32             len;
+    cyg_uint32             current_time_old;
+    cyg_uint32             current_time_new;
+    cyg_int32              diff_time;   
+    
+    
+
+    timeout_info.tx_timeout = timeout;
+    timeout_info.rx_timeout = timeout;
+    if (ENOERR != cyg_io_set_config(hCAN, CYG_IO_SET_CONFIG_CAN_TIMEOUT ,&timeout_info, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0");
+    }
+    
+    diag_printf("read timeout:  %d\n", timeout);
+    
+    //
+    // if the return code is -EINTR then we know that a timout occured. Normally the
+    // receive queue should be empty so we can expect a timeout here
+    //
+    current_time_old = (cyg_uint32)cyg_current_time();
+    len = sizeof(rx_event);
+    if (-EINTR == cyg_io_read(hCAN, &rx_event, &len))
+    {
+        current_time_new = (cyg_uint32)cyg_current_time();    
+        diff_time = current_time_new -  current_time_old;
+        diag_printf("measured time: %d\n\n", diff_time);
+        diff_time = diff_time - timeout;
+        
+        //
+        // If the measured value is smaller then the timeout value or if
+        // the difference is > 2 the we treat this as an error
+        //
+        if ((diff_time < 0) || (diff_time > 2))
+        {
+            CYG_TEST_FAIL_FINISH("Measured timeout time differs from /dev/can0 RX timeout value.");  
+        }
+    }
+    else
+    {
+        CYG_TEST_FAIL_FINISH("Timeout expected for /dev/can0");  
+    }
+}
+
+//===========================================================================
+//                             WRITER THREAD 
+//===========================================================================
+void can0_thread(cyg_addrword_t data)
+{
+    cyg_io_handle_t        hCAN0;
+    cyg_uint32             len;
+    cyg_uint32             blocking;
+    cyg_can_timeout_info_t timeout_info;
+   
+    
+    if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0)) 
+    {
+        CYG_TEST_FAIL_FINISH("Error opening /dev/can0");
+    }
+    
+    //
+    // the first thing we need to do is to switch to nonblocking calls because
+    // function calls with timeout require nonblocking calls
+    //
+    blocking = 0;
+    len = sizeof(blocking);
+    if (ENOERR != cyg_io_set_config(hCAN0, CYG_IO_SET_CONFIG_READ_BLOCKING ,&blocking, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error changing config of /dev/can0");
+    }
+      
+    //
+    // first we read the timeout configuration
+    //
+    len = sizeof(timeout_info);
+    if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_TIMEOUT ,&timeout_info, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0");
+    }
+    
+    //
+    // now we check the default timeout and a number of different timeout values
+    //
+    check_timeout(hCAN0, timeout_info.rx_timeout);
+    check_timeout(hCAN0, 10);
+    check_timeout(hCAN0, 20);
+    check_timeout(hCAN0, 50);
+    check_timeout(hCAN0, 100);
+    check_timeout(hCAN0, 200);
+    check_timeout(hCAN0, 500);
+
+        
+    CYG_TEST_PASS_FINISH("can_timeout test OK");                     
+}
+
+
+
+
+void
+cyg_start(void)
+{
+    CYG_TEST_INIT();
+    
+    //
+    // create the thread which access the CAN device driver
+    //
+    cyg_thread_create(4, can0_thread, 
+                        (cyg_addrword_t) 0,
+		                "can0_thread", 
+		                (void *) can0_thread_data.stack, 
+		                1024 * sizeof(long),
+		                &can0_thread_data.hdl, 
+		                &can0_thread_data.obj);
+		                
+    cyg_thread_resume(can0_thread_data.hdl);
+    
+    cyg_scheduler_start();
+}
+
+#else // CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
+#define N_A_MSG "Timeout support required for IO/CAN"
+#endif
+
+#else // CYGFUN_KERNEL_API_C
+#define N_A_MSG "Needs kernel C API"
+#endif
+
+#else // CYGPKG_IO_CAN && CYGPKG_KERNEL
+#define N_A_MSG "Needs IO/CAN and Kernel"
+#endif
+
+#ifdef N_A_MSG
+void
+cyg_start( void )
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA( N_A_MSG);
+}
+#endif // N_A_MSG
+
+// EOF can_timeout.c
new file mode 100644
--- /dev/null
+++ b/packages/devs/can/loop/current/tests/can_txevent.c
@@ -0,0 +1,264 @@
+//==========================================================================
+//
+//        can_txevent.c
+//
+//        Test CAN device driver timeouts
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     Uwe Kindler
+// Contributors:  Uwe Kindler
+// Date:          2005-08-07
+// Description:   Timeout test of CAN device driver
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+//                                INCLUDES
+//===========================================================================
+#include <pkgconf/system.h>
+
+#include <cyg/infra/testcase.h>         // test macros
+#include <cyg/infra/cyg_ass.h>          // assertion macros
+#include <cyg/infra/diag.h>
+
+// Package requirements
+#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL)
+
+#include <pkgconf/kernel.h>
+#include <cyg/io/io.h>
+#include <cyg/io/canio.h>
+
+// Package option requirements
+#if defined(CYGFUN_KERNEL_API_C)
+
+#include <cyg/hal/hal_arch.h>           // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/kernel/kapi.h>
+
+// tx event support required
+#if defined(CYGOPT_IO_CAN_TX_EVENT_SUPPORT)
+
+
+//===========================================================================
+//                               DATA TYPES
+//===========================================================================
+typedef struct st_thread_data
+{
+    cyg_thread   obj;
+    long         stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+    cyg_handle_t hdl;
+} thread_data_t;
+
+
+//===========================================================================
+//                              LOCAL DATA
+//===========================================================================
+cyg_thread_entry_t can0_thread;
+thread_data_t      can0_thread_data;
+
+
+//===========================================================================
+//                          LOCAL FUNCTIONS
+//===========================================================================
+#include "can_test_aux.inl" // include CAN test auxiliary functions
+
+
+//===========================================================================
+//                             WRITER THREAD 
+//===========================================================================
+void can0_thread(cyg_addrword_t data)
+{
+    cyg_io_handle_t    hCAN0;
+    cyg_uint32         len;
+    cyg_can_buf_info_t buf_info;
+    cyg_uint16         i;
+    cyg_can_event      rx_event;
+    cyg_can_message    tx_msg =
+    {
+        0x000,                                               // CAN identifier
+        {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7},    // 8 data bytes
+        CYGNUM_CAN_ID_STD,                                   // standard frame
+        CYGNUM_CAN_FRAME_DATA,                               // data frame
+        4,                                                   // data length code
+    };
+   
+    
+    if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0)) 
+    {
+        CYG_TEST_FAIL_FINISH("Error opening /dev/can0");
+    }
+    
+    //
+    // first we read the buffer info
+    //
+    len = sizeof(buf_info);
+    if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&buf_info, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0");
+    }
+    
+    //
+    // check if buffer is really empty
+    //
+    if (buf_info.rx_count != 0)
+    {
+        CYG_TEST_FAIL_FINISH("Receive buffer of /dev/can0 is not empty.");
+    }
+    
+    //
+    // now send messages - because TX events are supported each transmitted CAN message
+    // will cause a TX event that is filled into receive queue
+    //
+    diag_printf("Sending %d CAN messages to /dev/can0 \n", buf_info.rx_bufsize);
+    for (i = 0; i < buf_info.rx_bufsize; ++i)
+    {
+        tx_msg.id = i;
+        tx_msg.data[0] = i;
+        len = sizeof(tx_msg);
+        
+        if (ENOERR != cyg_io_write(hCAN0, &tx_msg, &len))
+        {
+            CYG_TEST_FAIL_FINISH("Error writing to /dev/can0");
+        }
+        else
+        {
+            print_can_msg(&tx_msg, "");
+        }
+    }
+    
+    //
+    // now we read the buffer info - we expect a completely filled recieve queue
+    //
+    len = sizeof(buf_info);
+    if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&buf_info, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0");
+    }
+    
+    //
+    // if receive queue is not completely filled, then we have an error here
+    //
+    if (buf_info.rx_bufsize != buf_info.rx_count)
+    {
+        diag_printf("RX bufsize: %d    events in RX buffer: %d\n", buf_info.rx_bufsize, buf_info.rx_count);
+        CYG_TEST_FAIL_FINISH("Receive queue of /dev/can0 not completely filled.");
+    }
+    
+    //
+    // now we read the receive queue
+    //
+    diag_printf("Receiving %d TX events from /dev/can0 \n", buf_info.rx_count);
+    for (i = 0; i < buf_info.rx_count; ++i)
+    {
+        len = sizeof(rx_event);
+        
+        if (ENOERR != cyg_io_read(hCAN0, &rx_event, &len))
+        {
+            CYG_TEST_FAIL_FINISH("Error reading from /dev/can0");
+        }
+        
+        //
+        // we expect only a set TX flag because no other events may arrive for the
+        // loopback driver
+        //
+        if (!(rx_event.flags & CYGNUM_CAN_EVENT_TX) || (rx_event.flags & !CYGNUM_CAN_EVENT_TX))
+        {
+            CYG_TEST_FAIL_FINISH("Unexpected receive event flags.");
+        }
+        
+        //
+        // Now check if TX events contain valid data - we know that the ID and the first
+        // data byte contain the message number
+        //
+        if ((rx_event.msg.id != i) || (rx_event.msg.data[0] != i))
+        {
+            CYG_TEST_FAIL_FINISH("Received invalid data in TX event");
+        }
+        else
+        {
+            print_can_msg(&rx_event.msg, "");
+        }     
+    } // for (i = 0; i < buf_info.rx_count; ++i)
+           
+    CYG_TEST_PASS_FINISH("can_txevent test OK");                     
+}
+
+
+
+void
+cyg_start(void)
+{
+    CYG_TEST_INIT();
+    
+    //
+    // create the thread which access the CAN device driver
+    //
+    cyg_thread_create(4, can0_thread, 
+                        (cyg_addrword_t) 0,
+		                "can0_thread", 
+		                (void *) can0_thread_data.stack, 
+		                1024 * sizeof(long),
+		                &can0_thread_data.hdl, 
+		                &can0_thread_data.obj);
+		                
+    cyg_thread_resume(can0_thread_data.hdl);
+    
+    cyg_scheduler_start();
+}
+
+#else // CYGOPT_IO_CAN_TX_EVENT_SUPPORT
+#define N_A_MSG "TX event support required for IO/CAN"
+#endif
+
+#else // CYGFUN_KERNEL_API_C
+#define N_A_MSG "Needs kernel C API"
+#endif
+
+#else // CYGPKG_IO_CAN && CYGPKG_KERNEL
+#define N_A_MSG "Needs IO/CAN and Kernel"
+#endif
+
+#ifdef N_A_MSG
+void
+cyg_start( void )
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA( N_A_MSG);
+}
+#endif // N_A_MSG
+
+// EOF serial4.c
new file mode 100644
--- /dev/null
+++ b/packages/devs/can/m68k/mcf52xx/current/ChangeLog
@@ -0,0 +1,38 @@
+2005-05-24  Uwe Kindler  <uwe_kindler@web.de>
+
+	* mcf52xx FlexCAN driver package created
+
+//===========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
new file mode 100644
--- /dev/null
+++ b/packages/devs/can/m68k/mcf52xx/current/cdl/can_mcf52xx.cdl
@@ -0,0 +1,369 @@
+# ====================================================================
+#
+#      can_mcf52xx.cdl
+#
+#      eCos MCF52xx FlexCAN configuration data
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 2003, 2004 eCosCentric Limited
+##
+## eCos is free software; you can redistribute it and/or modify it under
+## the terms of the GNU General Public License as published by the Free
+## Software Foundation; either version 2 or (at your option) any later version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+## WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License along
+## with eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):      Uwe Kindler
+# Contributors:
+# Date:           2005-05-17
+#
+#####DESCRIPTIONEND####
+# ====================================================================
+
+
+cdl_package CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN {
+    display       "CAN driver for FlexCAN module of coldfire mcf52xx family"
+
+    parent        CYGPKG_IO_CAN_DEVICES
+    active_if     CYGPKG_IO_CAN
+    active_if     CYGPKG_HAL_M68K_MCF52xx
+
+    requires      CYGPKG_ERROR
+
+    description   "
+           This package provides a generic CAN device driver for the on-chip
+           FlexCAN modules in MCF52xx ColdFire processors."
+    compile       -library=libextras.a   can_mcf52xx.c
+    define_proc {
+        puts $::cdl_system_header "/***** CAN driver proc output start *****/"
+        puts $::cdl_system_header "#define CYGDAT_IO_CAN_DEVICE_HEADER <pkgconf/devs_can_mcf52xx_flexcan.h>"
+        puts $::cdl_system_header "/*****  CAN driver proc output end  *****/"
+    }
+    
+    # Support up to two on-chip FlexCAN modules. The number varies between
+    # processor variants
+    for { set ::flexcan 0 } { $::flexcan < 2 } { incr ::flexcan } {
+    
+        cdl_interface CYGINT_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan] {
+            display     "Platform provides FlexCAN [set ::flexcan]"
+            flavor      bool
+            description "
+                This interface will be implemented if the specific coldfire
+                processor being used has an on-chip FlexCAN[set ::flexcan], and if
+                that FlexCAN is accessible on the target hardware."
+        }
+    
+        cdl_component CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan] {
+            display     "Allow access to the on-chip FlexCAN[set ::flexcan] via a CAN driver"
+            flavor      bool
+            active_if       CYGINT_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]
+            default_value   1
+            implements      CYGINT_IO_CAN_TIMESTAMP
+            
+            description "
+                If the application needs to access the on-chip FlexCAN[set ::flexcan]
+                via an eCos CAN driver then this option should be enabled."
+
+            cdl_option CYGDAT_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_NAME {
+                display     "Device name for FlexCAN [set ::flexcan]"
+                flavor      data
+                default_value   [format {"\"/dev/can%d\""} $::flexcan]
+                description "
+                    This option controls the name that an eCos application
+                    should use to access this device via cyg_io_lookup(),
+                    open(), or similar calls."
+            }
+
+        
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_KBAUD {
+                display     "Default baud rate for FlexCAN [set ::flexcan]"
+                flavor      data
+                default_value   100
+                legal_values    { 10 20 50 100 125 250 500 800 1000 }
+                description "This option determines the initial baud rate in KBaud for FlexCAN [set ::flexcan]"
+            }
+
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_QUEUESIZE_TX {
+                display     "Size of TX Queue for the FlexCAN [set ::flexcan] driver"
+                flavor      data
+                default_value   32
+                legal_values    16 to 512
+                description "
+                    The CAN device driver will run in interrupt mode and will
+                    perform buffering of outgoing data. This option controls the number
+                    of CAN messages the TX queue can store."
+            }
+            
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_QUEUESIZE_RX {
+                display     "Size of RX Queue for the FlexCAN [set ::flexcan] driver"
+                flavor      data
+                default_value   32
+                legal_values    16 to 512
+                description "
+                    The CAN device driver will run in interrupt mode and will
+                    perform buffering of incoming data. This option controls the number
+                    of CAN events the RX queue can store."
+            }
+            
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_RXMASK_GLOBAL {
+                display     "Receive mask for message buffers 0 - 13"
+                flavor      data
+                default_value   0x1FFFFFFF
+                description "
+                    The global RX-mask is composed of 4 bytes. The mask bits are
+                    applied to all Rx-Identifiers excluding Rx-buffers 14-15, that 
+                    have their specific Rx-mask. (0 corresponding incoming ID bit is 
+                    \"don’t care\". 1 corresponding ID bit is checked against the incoming 
+                    ID bit, to see if a match exists). By default the message buffers
+                    should only receive messages that exactly match the configured
+                    message buffer CAN identifier - that means alle bits are 1."
+            }
+            
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_RXMASK_14 {
+                display     "Receive mask for message buffer 14"
+                flavor      data
+                default_value   0x0
+                description "
+                    The RX-mask for message buffer 14 is composed of 4 bytes. The mask
+                    bits are applied to message buffer 14. (0 corresponding incoming ID 
+                    bit is \"don’t care\". 1 corresponding ID bit is checked against the 
+                    incoming ID bit, to see if a match exists). Message buffer 14 is
+                    the receive message buffer and should receive all available CAN
+                    messages - all bits are 0."
+            }
+            
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_RXMASK_15 {
+                display     "Receive mask for message buffer 15"
+                flavor      data
+                default_value   0x1FFFFFFF
+                description "
+                    The RX-mask for message buffer 15 is composed of 4 bytes. The mask
+                    bits are applied to message buffer 15. (0 corresponding incoming ID 
+                    bit is \"don’t care\". 1 corresponding ID bit is checked against the 
+                    incoming ID bit, to see if a match exists)."
+            }
+            
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN[set ::flexcan]_WAKEINT {
+                display     "Wake interrupt priority"
+                flavor      data
+                default_value   is_loaded(CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_WAKEINT) ? \
+                                CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_WAKEINT : \
+                                CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN
+                legal_values   CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN to CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MAX
+                description "
+                    Interrupt priority for wake interrupt."
+            }
+            
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN[set ::flexcan]_ERRINT {
+                display     "Error interrupt priority"
+                flavor      data
+                default_value   is_loaded(CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_ERRINT) ? \
+                                CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_ERRINT : \
+                                CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN
+                legal_values   CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN to CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MAX
+                description "
+                    Interrupt priority for error interrupt."
+            }
+            
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN[set ::flexcan]_BOFFINT {
+                display     "Bus off interrupt priority"
+                flavor      data
+                default_value   is_loaded(CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_BOFFINT) ? \
+                                CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_BOFFINT : \
+                                CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN
+                legal_values   CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN to CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MAX
+                description "
+                    Interrupt priority for bus off interrupt."
+            }
+            
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_DEFAULT_RX_MBOX {
+                display "Default receive message buffer"
+                flavor  data
+                calculated    14
+                legal_values  0 to 15
+                description "
+                    By default one message buffer will be used for reception of
+                    all CAN messages. This option selects one of the 16 message
+                    buffers for reception."
+            }
+            
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_DEFAULT_TX_MBOX {
+                display "Default transmit message buffer"
+                flavor  data
+                calculated    15
+                legal_values  0 to 15
+                description "
+                    By default one message buffer will be used for message transmission.
+                    This option selects one of the 16 FlexCAN message buffers for
+                    transmission."
+            }
+            
+            cdl_component CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_MBOXCFG {
+                display     "Message buffer configuration"
+                flavor       none
+                active_if       CYGINT_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]
+                description "
+                    The FlexCAN module contains 16 flexible message buffers of 0-8 bytes 
+                    data length, each configurable as Rx or Tx, all supporting standard and 
+                    extended messages. At the moment a fixed configuration is used for
+                    TX and RX message buffers but in future this may be configurable."
+                
+                cdl_component CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_MBOX14_CFG {
+                    display "Message buffer 14 configuration"
+                    flavor  none
+                    active_if       CYGINT_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]
+                    description "
+                       Configuration of FlexCAN message buffer 14."
+                   
+                    cdl_option CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN[set ::flexcan]_MBOX14 {
+                        display     "Interrupt priority."
+                        flavor      data
+                        default_value   is_loaded(CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_MBOX14) ? \
+                                    CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_MBOX14 : \
+                                    CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN
+                        legal_values   CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN to CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MAX
+                        description "
+                            Interrupt priority for message buffer 14"
+                    }
+                    
+                    cdl_option CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_MBOX14_IS_TX {
+                        display "Use for transmit"
+                        flavor  bool
+                        active_if       CYGINT_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]
+                        calculated      0
+                        description "
+                            This option controls if this message buffer is used for sending
+                            or receiving messages. Currently this option is not configurable
+                            and message box 14 is used for reception of CAN messages."
+                        
+                    }
+                }
+                
+                cdl_component CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_MBOX15_CFG {
+                    display "Message buffer 15 configuration"
+                    flavor  none
+                    active_if       CYGINT_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]
+                    description "
+                       Configuration of FlexCAN message buffer 15."
+                   
+                    cdl_option CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN[set ::flexcan]_MBOX15 {
+                        display     "Interrupt priority."
+                        flavor      data
+                        default_value   is_loaded(CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_MBOX15) ? \
+                                    CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_MBOX15 : \
+                                    CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN
+                        legal_values   CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN to CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MAX
+                        description "
+                            Interrupt priority for message buffer 15"
+                    }
+                    
+                    cdl_option CYGOPT_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_MBOX15_IS_TX {
+                        display "Use for transmit"
+                        flavor  bool
+                        active_if       CYGINT_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]
+                        calculated      1
+                        description "
+                            This option controls if this message buffer is used for sending
+                            or receiving messages. Currently this option is not configurable
+                            and message box 15 is used for transmission of CAN messages."
+                        
+                    }
+                }
+            } 
+        }    
+    }
+    
+    cdl_option CYGBLD_DEVS_CAN_MCF52xx_FLEXCAN_EXTRA_TESTS {
+        display "Build extra FlexCAN tests"
+        default_value 0
+        no_define
+        description "
+            This option enables the building of some extra tests which
+            can be used when testing / debugging FlexCAN drivers. These
+            are not built by default since they do not use the dedicated
+            testing infrastructure. All tests require a properly configured
+            CAN network with a second CAN node that can send and receive
+            CAN messages."
+
+        make -priority 320 {
+            <PREFIX>/bin/flexcan_load : <PACKAGE>/tests/flexcan_load.c
+            @sh -c "mkdir -p tests $(dir $@)"
+            $(CC) -c $(INCLUDE_PATH) -Wp,-MD,deps.tmp -I$(dir $<) $(CFLAGS) -o tests/flexcan_load.o $<
+            @echo $@ ": \\" > $(notdir $@).deps
+            @echo $(wildcard $(PREFIX)/lib/*) " \\" >> $(notdir $@).deps
+            @tail -n +2 deps.tmp >> $(notdir $@).deps
+            @echo >> $(notdir $@).deps
+            @rm deps.tmp
+            $(CC) $(LDFLAGS) -L$(PREFIX)/lib -Ttarget.ld -o $@ tests/flexcan_load.o
+        }
+        
+        make -priority 320 {
+            <PREFIX>/bin/flexcan_remote : <PACKAGE>/tests/flexcan_remote.c
+            @sh -c "mkdir -p tests $(dir $@)"
+            $(CC) -c $(INCLUDE_PATH) -Wp,-MD,deps.tmp -I$(dir $<) $(CFLAGS) -o tests/flexcan_remote.o $<
+            @echo $@ ": \\" > $(notdir $@).deps
+            @echo $(wildcard $(PREFIX)/lib/*) " \\" >> $(notdir $@).deps
+            @tail -n +2 deps.tmp >> $(notdir $@).deps
+            @echo >> $(notdir $@).deps
+            @rm deps.tmp
+            $(CC) $(LDFLAGS) -L$(PREFIX)/lib -Ttarget.ld -o $@ tests/flexcan_remote.o
+        }
+    }
+
+
+
+    cdl_component CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN_OPTIONS {
+        display "FlexCAN device driver build options"
+        flavor  none
+        description   "
+        Package specific build options including control over
+        compiler flags used only in building this package,
+        and details of which tests are built."
+
+        cdl_option CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN_CFLAGS_ADD {
+            display "Additional compiler flags"
+            flavor  data
+            no_define
+            default_value { "" }
+            description   "
+                This option modifies the set of compiler flags for
+                building these CAN device drivers. These flags are
+                used in addition to the set of global flags."
+        }
+
+        cdl_option CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN_CFLAGS_REMOVE {
+            display "Suppressed compiler flags"
+            flavor  data
+            no_define
+            default_value { "" }
+            description   "
+                This option modifies the set of compiler flags for
+                building these CAN device drivers. These flags are
+                removed from the set of global flags if present."
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/packages/devs/can/m68k/mcf52xx/current/src/can_mcf52xx.c
@@ -0,0 +1,1473 @@
+//==========================================================================
+//
+//      devs/serial/m68k/flexcan/current/src/can_mcf_flexcan.c
+//
+//      CAN driver for Motorola coldfire processors
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2003 Gary Thomas
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Uwe Kindler
+// Contributors: Uwe Kindler
+// Date:         2005-05-12
+// Purpose:      support coldfire on-chip flexcan moduls
+// Description: 
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+
+//==========================================================================
+//                              INCLUDES
+//==========================================================================
+#include <pkgconf/system.h>
+#include <pkgconf/io_can.h>
+#include <pkgconf/devs_can_mcf52xx_flexcan.h>
+
+#include <cyg/infra/diag.h>
+
+#include <cyg/io/io.h>
+#include <cyg/io/devtab.h>
+#include <cyg/io/can.h>
+
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_intr.h>
+#include <cyg/hal/hal_io.h>
+
+
+//===========================================================================
+//                                DEFINES  
+//===========================================================================
+
+//
+// we define our own ste of register bits in order to be independent from
+// platform specific names
+//
+
+//---------------------------------------------------------------------------
+// MCR regsiter bits
+//
+#define FLEXCAN_MCR_STOP                    (0x01 << 15)
+#define FLEXCAN_MCR_FRZ                     (0x01 << 14)
+#define FLEXCAN_MCR_HALT                    (0x01 << 12)
+#define FLEXCAN_MCR_NOTRDY                  (0x01 << 11)
+#define FLEXCAN_MCR_WAKEMSK                 (0x01 << 10)
+#define FLEXCAN_MCR_SOFTRST                 (0x01 << 9)
+#define FLEXCAN_MCR_FRZACK                  (0x01 << 8)
+#define FLEXCAN_MCR_SUPV                    (0x01 << 7)
+#define FLEXCAN_MCR_SELFWAKE                (0x01 << 6)
+#define FLEXCAN_MCR_APS                     (0x01 << 5)
+#define FLEXCAN_MCR_STOPACK                 (0x01 << 4)
+
+
+//---------------------------------------------------------------------------
+// CTRL0 register bits
+//
+#define FLEXCAN_CTRL0_BOFFMSK                   (0x01 << 7)
+#define FLEXCAN_CTRL0_ERRMASK                   (0x01 << 6)
+#define FLEXCAN_CTRL0_RXMODE                    (0x01 << 2)
+#define FLEXCAN_CTRL0_RXMODE_0_DOMINANT         (0x00 << 2)
+#define FLEXCAN_CTRL0_RXMODE_1_DOMINANT         (0x01 << 2)
+#define FLEXCAN_CTRL0_TXMODE_MASK               (0x03 << 0)
+#define FLEXCAN_CTRL0_TXMODE_SHIFT              0
+#define FLEXCAN_CTRL0_TXMODE_FULL_0_DOMINANT    (0x00 << 0)
+#define FLEXCAN_CTRL0_TXMODE_FULL_1_DOMINANT    (0x01 << 0)
+#define FLEXCAN_CTRL0_TXMODE_OPEN_0_DOMINANT    (0x02 << 0)
+
+
+//---------------------------------------------------------------------------
+// CTRL1 register bits
+//
+#define FLEXCAN_CTRL1_SAMP                      (0x01 << 7)
+#define FLEXCAN_CTRL1_TSYNC                     (0x01 << 5)
+#define FLEXCAN_CTRL1_LBUF                      (0x01 << 4)
+#define FLEXCAN_CTRL1_LOM                       (0x01 << 3)
+#define FLEXCAN_CTRL1_PROPSEG_MASK              (0x07 << 0)
+#define FLEXCAN_CTRL1_PROPSEG_SHIFT             0
+
+
+//---------------------------------------------------------------------------
+// CTRL2 register bits
+//
+#define FLEXCAN_CTRL2_RJW_MASK                  (0x03 << 6)
+#define FLEXCAN_CTRL2_RJW_SHIFT                 6
+#define FLEXCAN_CTRL2_PSEG1_MASK                (0x07 << 3)
+#define FLEXCAN_CTRL2_PSEG1_SHIFT               3
+#define FLEXCAN_CTRL2_PSEG2_MASK                (0x07 << 0)
+#define FLEXCAN_CTRL2_PSEG2_SHIFT               0
+
+//---------------------------------------------------------------------------
+// ESTAT register bits
+//
+#define FLEXCAN_ESTAT_BITERR_MASK               (0x03 << 14)
+#define FLEXCAN_ESTAT_BITERR_SHIFT              14
+#define FLEXCAN_ESTAT_BITERR_NONE               (0x00 << 14)
+#define FLEXCAN_ESTAT_BITERR_DOMINANT_RECESSIVE (0x01 << 14)
+#define FLEXCAN_ESTAT_BITERR_RECESSIVE_DOMINANT (0x02 << 14)
+#define FLEXCAN_ESTAT_ACKERR                    (0x01 << 13)
+#define FLEXCAN_ESTAT_CRCERR                    (0x01 << 12)
+#define FLEXCAN_ESTAT_FORMERR                   (0x01 << 11)
+#define FLEXCAN_ESTAT_STUFFERR                  (0x01 << 10)
+#define FLEXCAN_ESTAT_TXWARN                    (0x01 << 9)
+#define FLEXCAN_ESTAT_RXWARN                    (0x01 << 8)
+#define FLEXCAN_ESTAT_IDLE                      (0x01 << 7)
+#define FLEXCAN_ESTAT_TX_RX                     (0x01 << 6)
+#define FLEXCAN_ESTAT_FCS_MASK                  (0x03 << 4)
+#define FLEXCAN_ESTAT_FCS_SHIFT                 4
+#define FLEXCAN_ESTAT_FCS_ERROR_ACTIVE          (0x00 << 4)
+#define FLEXCAN_ESTAT_FCS_ERROR_PASSIVE         (0x01 << 4)
+#define FLEXCAN_ESTAT_BOFFINT                   (0x01 << 2)
+#define FLEXCAN_ESTAT_ERRINT                    (0x01 << 1)
+#define FLEXCAN_ESTAT_WAKEINT                   (0x01 << 0)
+
+//
+// For receive event calls we use these two identifiers for
+// err and bus off events - message boxes use 0 - 15
+//
+#define FLEXCAN_ERR_EVENT                       16
+#define FLEXCAN_BUSOFF_EVENT                    17
+
+
+//---------------------------------------------------------------------------
+// message buffer cfg bits
+//
+#define MBOX_RXCODE_NOT_ACTIVE 0x00
+#define MBOX_RXCODE_BUSY       0x10
+#define MBOX_RXCODE_EMPTY      0x40
+#define MBOX_RXCODE_FULL       0x20
+#define MBOX_RXCODE_OVERRUN    0x60
+
+#define MBOX_TXCODE_NOT_READY  0x80
+#define MBOX_TXCODE_TRANSMIT   0xC0
+#define MBOX_TXCODE_RESPONSE   0xA0
+
+#define MBOX_DATA_FRAME        0x00 // data frame
+#define MBOX_REMOTE_FRAME      0x01 // remote frame
+#define MBOX_STD_ID            0x00 // standard identifier
+#define MBOX_EXT_ID            0x01 // remote identifier
+#define MBOX_TX                0x08 // tx message box
+#define MBOX_RX                0x00 // rx messge box
+
+#define MBOX_CFG_IDE           0x08
+#define MBOX_CFG_RTR_EXT       0x01
+#define MBOX_CFG_RTR_STD       0x10
+#define MBOX_CFG_SSR           0x10
+#define MBOX_CFG_DLC_MASK      0x0F
+#define MBOX_CFG_STAT_MASK     0xF0
+
+
+//===========================================================================
+//                                 DATA TYPES
+//===========================================================================
+//
+// configuration info for flexcan message buffer
+//
+typedef struct flexcan_mbox_info_st
+{
+    cyg_vector_t  isr_vec;
+    int           isr_priority;
+    cyg_interrupt interrupt;
+    cyg_handle_t  interrupt_handle;   
+    cyg_uint8     num;  
+} flexcan_mbox_info; 
+
+//
+// flexcan interrupt (busoff, err, wake) data
+//
+typedef struct flexcan_int_st
+{
+    cyg_vector_t        isr_vec;  
+    int                 isr_priority;
+    cyg_interrupt       interrupt;
+    cyg_handle_t        interrupt_handle;
+} flexcan_int;
+
+//
+// flexcan message box initialisation
+//
+#define FLEXCAN_MBOX_INIT(_mbox0_vec, _prio, _mbox_no) { \
+    isr_vec      : (_mbox0_vec) + (_mbox_no),            \
+    isr_priority : (_prio),                              \
+    num          : (_mbox_no)                            \
+}
+
+//
+// Interrupt initialisation
+//
+#define FLEXCAN_INT_INIT(_vec, _prio) \
+{                                     \
+    isr_vec      : (_vec),            \
+    isr_priority : (_prio)            \
+}
+
+//
+// flexcan configuration 
+//
+typedef struct flexcan_info 
+{
+    cyg_uint8          *base;          // base address of flexcan modul
+    cyg_vector_t        isr_vec_mbox0; // vector number of ISR vector of first message box
+    flexcan_mbox_info   rx_mbox;       // rx message box interrupt
+    flexcan_mbox_info   tx_mbox;       // tx message box interrupt
+    cyg_uint32          last_tx_id;    // last transmitted message
+    bool                tx_busy;       // indicates if transmit process ic currently running
+    
+    cyg_uint32          rxgmask;       // acceptance filter for message box 0 - 13
+    cyg_uint32          rx14mask;      // acceptance filter for message box 14
+    cyg_uint32          rx15mask;      // acceptance filter for message box 15
+    
+    flexcan_int         boff_int;      // bus off interrupt data
+    flexcan_int         err_int;       // error interrupt data
+ 
+    cyg_uint32          timeout_rd;
+    cyg_uint32          timeout_wr;
+    cyg_uint16          mbox_alloc_flags;// these bits are used to indicate which message buffers are already alloceted and which ones are free
+#ifdef FLEXCAN_CAN_STATS
+    cyg_uint32          isr_count;
+    cyg_uint32          dsr_count;
+    cyg_uint32          rx_bytes;
+    cyg_uint32          tx_bytes;
+    cyg_uint32          rx_errors;
+#endif  
+} flexcan_info;
+
+
+//
+// flexcan info initialisation
+//
+#define FLEXCAN_INFO(_l,                                                \
+                     _baseaddr,                                         \
+                     _isr_vec_mbox0,                                    \
+                     _rx_mbox_no, _rx_isr_prio,                         \
+                     _tx_mbox_no, _tx_isr_prio,                         \
+                     _boff_isr_vec, _boff_isr_prio,                     \
+                     _err_isr_vec, _err_isr_prio)                       \
+flexcan_info _l = {                                                     \
+    (void *)( _baseaddr),                                               \
+    (_isr_vec_mbox0),                                                   \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_rx_isr_prio), (_rx_mbox_no)), \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_tx_isr_prio), (_tx_mbox_no)), \
+    0xFFFFFFFF,                                                         \
+    false,                                                              \
+    rxgmask       : CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_RXMASK_GLOBAL,     \
+    rx14mask      : CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_RXMASK_14,         \
+    rx15mask      : CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_RXMASK_15,         \
+    boff_int      : FLEXCAN_INT_INIT(_boff_isr_vec, _boff_isr_prio),    \
+    err_int       : FLEXCAN_INT_INIT(_err_isr_vec, _err_isr_prio)       \
+};
+
+
+//===========================================================================
+//                          GLOBAL DATA
+//===========================================================================
+//
+// Note: two levels of macro are required to get proper expansion.
+//
+#define _FLEXCAN_MBOX_INTPRIO(n) CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX##n
+#define FLEXCAN_MBOX_INTPRIO(n) _FLEXCAN_MBOX_INTPRIO(n)
+
+//
+// FlexCAN channel initialisation
+//
+FLEXCAN_INFO(flexcan_can0_info, 
+             HAL_MCF52xx_MBAR + HAL_MCF52xx_FLEXCAN0_BASE,
+             HAL_MCF52xx_FLEXCAN0_MBOX0_ISRVEC,
+             CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_RX_MBOX, 
+             FLEXCAN_MBOX_INTPRIO(CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_RX_MBOX),
+             CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_TX_MBOX, 
+             FLEXCAN_MBOX_INTPRIO(CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_TX_MBOX),
+             HAL_MCF52xx_FLEXCAN0_BOFF_ISRVEC,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_BOFFINT,  
+             HAL_MCF52xx_FLEXCAN0_ERR_ISRVEC,          
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_ERRINT);
+
+//
+// message box structure
+//
+typedef struct flexcan_mbox
+{
+    cyg_uint8  timestamp;
+    cyg_uint8  ctrlstat;
+    cyg_uint16 id_hi;
+    cyg_uint16 id_lo;
+    cyg_uint8  data[8];
+    cyg_uint16 reserved;
+} flexcan_mbox;
+
+//
+// flexcan register layout
+//
+typedef struct flexcan_regs
+{
+    cyg_uint16 CANMCR;       // 0x00
+    cyg_uint16 reserved0[2]; // 0x02
+    cyg_uint8  CANCTRL0;     // 0x06
+    cyg_uint8  CANCTRL1;     // 0x07
+    cyg_uint8  PRESDIV;      // 0x08
+    cyg_uint8  CANCTRL2;     // 0x09
+    cyg_uint16 TIMER;        // 0x0A
+    cyg_uint16 reserved1[2]; // 0x0C
+    cyg_uint16 RXGMASK_HI;   // 0x10
+    cyg_uint16 RXGMASK_LO;   // 0x12
+    cyg_uint16 RX14MASK_HI;  // 0x14
+    cyg_uint16 RX14MASK_LO;  // 0x16
+    cyg_uint16 RX15MASK_HI;  // 0x18
+    cyg_uint16 RX15MASK_LO;  // 0x1A
+    cyg_uint16 reserved2[2]; // 0x1C
+    cyg_uint16 ESTAT;        // 0x20
+    cyg_uint16 IMASK;        // 0x22
+    cyg_uint16 IFLAG;        // 0x24
+    cyg_uint8  RXERRCNT;     // 0x26
+    cyg_uint8  TXERRCNT;     // 0x27
+    cyg_uint16 reserved3[44];// 0x28
+    flexcan_mbox mbox[16]; // 0x80
+} flexcan_regs;
+
+
+//===========================================================================
+//                                 LOCAL DATA
+//===========================================================================
+static cyg_uint16 flexcan_baud_rates[] = {
+    0,      // Unused
+    10,     // 10 kbit/s
+    20,     // 20
+    50,     // 50
+    100,    // 100
+    125,    // 125
+    250,    // 250
+    500,    // 500
+    800,    // 800
+    1000,   // 1000 kbit/s
+};
+
+
+//===========================================================================
+//                              PROTOTYPES
+//===========================================================================
+static bool        flexcan_init(struct cyg_devtab_entry* devtab_entry);
+static Cyg_ErrNo   flexcan_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name);
+static Cyg_ErrNo   flexcan_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len);
+static bool        flexcan_putmsg(can_channel *priv, cyg_can_message *pmsg, void *pdata);
+static bool        flexcan_getevent(can_channel *priv, cyg_can_event *pevent, void *pdata);
+static void        flexcan_start_xmit(can_channel* chan);
+static void        flexcan_stop_xmit(can_channel* chan);
+
+//
+// TX and RX ISRs and DSRs
+//
+static cyg_uint32  flexcan_mbox_rx_isr(cyg_vector_t, cyg_addrword_t);
+static void        flexcan_mbox_rx_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
+static cyg_uint32  flexcan_mbox_tx_isr(cyg_vector_t, cyg_addrword_t);
+static void        flexcan_mbox_tx_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
+
+//
+// All other flexcan interrupt handlers
+//
+static cyg_uint32  flexcan_err_isr(cyg_vector_t, cyg_addrword_t);
+static void        flexcan_err_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
+static cyg_uint32  flexcan_busoff_isr(cyg_vector_t, cyg_addrword_t);
+static void        flexcan_busoff_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
+
+
+static bool flexcan_cfg_mbox_tx(flexcan_mbox *pmbox, cyg_can_message  *pmsg, bool rtr);
+static void flexcan_cfg_mbox_rx(flexcan_mbox *pmbox, cyg_uint32 canid, cyg_uint8 ext);
+static void flexcan_read_from_mbox(can_channel *chan, cyg_uint8 mbox, cyg_can_event *pevent, cyg_uint8 *ctrlstat);
+static void flexcan_set_acceptance_mask(cyg_uint16 *rxmask_reg, cyg_uint32 mask, cyg_uint8 ext);
+static void flexcan_start_chip(can_channel *chan);
+static bool flexcan_set_baud(can_channel *chan, cyg_uint16 baudrate);
+static bool flexcan_config(can_channel* chan, cyg_can_info_t* config, cyg_bool init);
+
+
+CAN_LOWLEVEL_FUNS(flexcan_lowlevel_funs,
+                  flexcan_putmsg,
+                  flexcan_getevent,
+                  flexcan_set_config,
+                  flexcan_start_xmit,
+                  flexcan_stop_xmit
+     );
+
+
+cyg_can_event    flexcan_can0_rxbuf[CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_RX]; // buffer for 32 rx can events
+cyg_can_message  flexcan_can0_txbuf[CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_TX]; // buffer for 32 tx can messageds
+
+
+CAN_CHANNEL_USING_INTERRUPTS(flexcan_can0_chan,
+                             flexcan_lowlevel_funs,
+                             flexcan_can0_info,
+                             CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_KBAUD),
+                             flexcan_can0_txbuf, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_TX,
+                             flexcan_can0_rxbuf, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_RX
+    );
+
+
+DEVTAB_ENTRY(flexcan_devtab, 
+             CYGDAT_DEVS_CAN_MCF52xx_FLEXCAN0_NAME,
+             0,                     // Does not depend on a lower level interface
+             &cyg_io_can_devio, 
+             flexcan_init, 
+             flexcan_lookup,        // CAN driver may need initializing
+             &flexcan_can0_chan
+    );
+
+
+//===========================================================================
+//  Lookup the device and return its handle
+//===========================================================================
+static Cyg_ErrNo
+flexcan_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name)
+{
+    can_channel* chan    = (can_channel*) (*tab)->priv;
+    (chan->callbacks->can_init)(chan);
+    
+    return ENOERR;
+}
+
+
+//===========================================================================
+//  Set device configuration
+//===========================================================================
+static Cyg_ErrNo
+flexcan_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len)
+{
+    Cyg_ErrNo     res = ENOERR;
+    
+    switch(key) 
+    {
+        case CYG_IO_SET_CONFIG_CAN_INFO:
+             {
+                 cyg_can_info_t*  config = (cyg_can_info_t*) buf;
+                 if (*len < sizeof(cyg_can_info_t)) 
+                 {
+                    return -EINVAL;
+                 }
+                 *len = sizeof(cyg_can_info_t);
+                 if (!flexcan_config(chan, config, false)) 
+                 {
+                    return -EINVAL;
+                 }
+            }
+            break;
+            
+        case CYG_IO_SET_CONFIG_CAN_RTR_BUF:
+             { 
+                 cyg_uint8          i;
+                 cyg_uint16         alloc_mask = 0x0001;
+                 flexcan_info      *info       = (flexcan_info *)chan->dev_priv;
+                 flexcan_regs      *flexcan    = (flexcan_regs *)info->base;
+                 cyg_can_rtr_buf_t *rtr_buf    = (cyg_can_rtr_buf_t*) buf;
+                 
+             
+                 if (*len != sizeof(cyg_can_rtr_buf_t)) 
+                 {
+                    return -EINVAL;
+                 }
+                 *len = sizeof(cyg_can_rtr_buf_t);
+                 
+                 //
+                 // If we need to create a new remote buffer then we check if there
+                 // is one message box free and then setup this box for remote frame
+                 // transmission
+                 //
+                 if (CYGNUM_CAN_RTR_BUF_INIT == rtr_buf->handle)
+                 {
+                    rtr_buf->handle = CYGNUM_CAN_RTR_BUF_NA;
+                    for (i = 0; i < 14; ++i)
+                    {
+                        if (!(info->mbox_alloc_flags & alloc_mask))
+                        {
+                            rtr_buf->handle = i;
+                            info->mbox_alloc_flags |= alloc_mask;
+                            break;
+                        }
+                        alloc_mask <<= 1;
+                     }
+                 } // if (CYGNUM_CAN_RTR_BUF_INIT == rtr_buf->handle)
+                 
+                 //
+                 // If we have a valid rtr buf handle then we can store data into 
+                 // rtr message box
+                 //
+                 if ((rtr_buf->handle >= 0) && (rtr_buf->handle < 14))
+                 {
+                     flexcan_cfg_mbox_tx(&flexcan->mbox[rtr_buf->handle], &rtr_buf->msg, true);
+                 }
+                 else
+                 {
+                    return -EINVAL;
+                 }
+                 
+             }
+             break;
+         
+    } // switch (key)
+    
+    return res;
+}
+
+
+//===========================================================================
+//  Read one event from can hardware
+//===========================================================================
+static bool flexcan_getevent(can_channel *chan, cyg_can_event *pevent, void *pdata)
+{
+    flexcan_info *info           = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan        = (flexcan_regs *)info->base;
+    cyg_uint8     mbox_ctrlstat;
+    bool          res            = true;
+    cyg_uint8     event_id       = *((cyg_uint8 *)pdata);
+    cyg_uint16    estat;
+        
+    //
+    // if event_id is 0 - 15 the we have a message box event - if is
+    //
+    if (event_id < FLEXCAN_ERR_EVENT)
+    {   
+        //
+        // read data from message box - during processing of this function
+        // the message box is locked and cannot receive further messages
+        //
+        flexcan_read_from_mbox(chan, event_id, pevent, &mbox_ctrlstat); 
+
+#ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT    
+        if (pevent->msg.id == info->last_tx_id)
+        {
+            pevent->flags = CYGNUM_CAN_EVENT_TX;
+        }
+        else
+        {
+            pevent->flags = CYGNUM_CAN_EVENT_RX;
+        } 
+#else // !CYGOPT_IO_CAN_TX_EVENT_SUPPORT
+        //
+        // If tx events are not supported and we received a self transmitted frame
+        // then this is not really an rx event and we return false. We rely on the
+        // fact here that two devices in network do not send the same identifier
+        //
+        if (pevent->msg.id == info->last_tx_id)    {   
+            info->last_tx_id = 0xFFFFFFFF; // set last received ID to an invalid value
+            res = false; 
+        }
+    
+        pevent->flags = CYGNUM_CAN_EVENT_RX;
+#endif
+    
+        //
+        // check if an overun occured in this message box
+        //
+        if ((mbox_ctrlstat & MBOX_RXCODE_OVERRUN) == MBOX_RXCODE_OVERRUN)
+        {
+            pevent->flags |= CYGNUM_CAN_EVENT_OVERRUN_RX;
+        }
+    }
+    else // (event_id >= FLEXCAN_ERR_EVENT)
+    {
+        //
+        // We have an status event - check if it is an bus off interrupt or an
+        // error interrupt and provide error information to upper layer
+        //
+        HAL_READ_UINT16(&flexcan->ESTAT, estat);
+        pevent->msg.data[0] = estat & 0xFF;
+        pevent->msg.data[1] = (estat >> 8) & 0xFF; 
+        HAL_READ_UINT8(&flexcan->RXERRCNT, pevent->msg.data[2]);
+        HAL_READ_UINT8(&flexcan->TXERRCNT, pevent->msg.data[3]);
+        switch (event_id)
+        {
+            case FLEXCAN_ERR_EVENT :
+                 //
+                 // indicate error passive event and provide content of estat register
+                 // for a more precise error information
+                 //
+                 if (estat & FLEXCAN_ESTAT_FCS_ERROR_PASSIVE)
+                 {
+                    pevent->flags = CYGNUM_CAN_EVENT_ERR_PASSIVE;
+                 }
+                 //
+                 // If we are not in error passive state then we check if the
+                 // error counters reached the warning level
+                 //
+                 else
+                 {               
+                     //
+                     // indicate tx error counter warning level reached
+                     //
+                     if (estat & FLEXCAN_ESTAT_TXWARN)
+                     {
+                         pevent->flags |= CYGNUM_CAN_EVENT_WARNING_TX;
+                     }
+                 
+                     //
+                     // indicate rx error counter warning level reached
+                     //
+                     if (estat & FLEXCAN_ESTAT_RXWARN)
+                     {
+                         pevent->flags |= CYGNUM_CAN_EVENT_WARNING_RX;
+                     }
+                 }
+                 break;
+                 
+            case FLEXCAN_BUSOFF_EVENT:
+                 pevent->flags = CYGNUM_CAN_EVENT_BUS_OFF;
+                 break;
+        } // switch (event_id)
+    }
+
+    return res;
+}
+
+
+//===========================================================================
+// Send one CAN message to CAN hardware
+//===========================================================================
+static bool flexcan_putmsg(can_channel *chan, cyg_can_message *pmsg, void *pdata)
+{
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint8        mbox = *((cyg_uint8 *)pdata);
+    cyg_uint16       iflag;
+   
+    HAL_READ_UINT16(&flexcan->IFLAG, iflag);
+    
+    //
+    // check if device is busy sending a message
+    //
+    if (info->tx_busy)
+    {
+        //
+        // if devise is busy and the interrupt flag is set, then we know
+        // that device is not busy any longer - if more message boxes are
+        // used for transmitting then tx_busy should be part of a message box
+        // structure to keep track of the state of different message boxes
+        //
+        if (iflag & (0x0001 << mbox))
+        {
+            HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));
+        }
+        else
+        {
+            return false;
+        }
+    }
+    
+    info->tx_busy    = true;     // mark transmitter as busy
+    info->last_tx_id = pmsg->id; // store message in order to identify self recieved frames
+    flexcan_cfg_mbox_tx(&flexcan->mbox[mbox], pmsg, false);
+    
+    return true;
+}
+
+
+//===========================================================================
+// Flexcan start xmit
+//===========================================================================
+static void flexcan_start_xmit(can_channel* chan)
+{
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16    imask;
+    CYG_INTERRUPT_STATE     saved_state;
+
+    HAL_DISABLE_INTERRUPTS(saved_state);
+    
+    //
+    // Now enable message box 15 interrupts
+    //
+    HAL_READ_UINT16(&flexcan->IMASK, imask);
+    HAL_WRITE_UINT16(&flexcan->IMASK, imask | (0x0001 << info->tx_mbox.num));
+    
+    //
+    // kick transmitter
+    //
+    chan->callbacks->xmt_msg(chan, &info->tx_mbox.num);  // Kick transmitter (if necessary)
+    
+    HAL_RESTORE_INTERRUPTS(saved_state);
+}
+
+
+//===========================================================================
+// Flexcan start xmit
+//===========================================================================
+static void flexcan_stop_xmit(can_channel* chan)
+{
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16    imask;
+    CYG_INTERRUPT_STATE     saved_state;
+
+    HAL_DISABLE_INTERRUPTS(saved_state);
+    
+    //
+    // Now disable message box 15 interrupts
+    //
+    HAL_READ_UINT16(&flexcan->IMASK, imask);
+    HAL_WRITE_UINT16(&flexcan->IMASK, imask & ~(0x0001 << info->tx_mbox.num));
+
+    HAL_RESTORE_INTERRUPTS(saved_state);
+}
+
+
+//===========================================================================
+// Configure flexcan channel
+//===========================================================================
+static bool flexcan_config(can_channel* chan, cyg_can_info_t* config, cyg_bool init)
+{
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16    tmp16;
+    cyg_uint8     tmp8;
+    cyg_uint8     i;
+    
+    if (init)
+    {
+#if defined(CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN0) && defined(HAL_MCF52xx_FLEXCAN0_PROC_INIT)
+        if (info == &flexcan_can0_info) {
+            HAL_MCF52xx_FLEXCAN0_PROC_INIT();
+        }
+#endif
+        
+        //
+        // Issue a reset in order to go into halt mode. The reset will set the
+        // the halt bit in mcr
+        //
+        HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
+        tmp16 &= ~FLEXCAN_MCR_FRZ;
+        HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16);
+        tmp16 |= FLEXCAN_MCR_SOFTRST;
+        HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16);
+        HAL_DELAY_US(10);
+    
+        //
+        // Check reset status
+        //
+        HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
+        if (tmp16 & FLEXCAN_MCR_SOFTRST)
+        {
+            return false;
+        }
+    
+        //
+        // Initialize the transmit and receive pin modes
+        //
+        HAL_WRITE_UINT8(&flexcan->CANCTRL0 , (FLEXCAN_CTRL0_TXMODE_FULL_0_DOMINANT  
+                                            | FLEXCAN_CTRL0_RXMODE_0_DOMINANT)
+                                            & ~FLEXCAN_CTRL0_BOFFMSK
+                                            & ~FLEXCAN_CTRL0_ERRMASK);
+                                            
+        //
+        // setup message box acceptance filter
+        //
+        flexcan_set_acceptance_mask(&flexcan->RXGMASK_HI,  info->rxgmask, 0);
+        flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, info->rx14mask, 0);
+        flexcan_set_acceptance_mask(&flexcan->RX15MASK_HI, info->rx15mask, 0);                                          
+    } // if (init)
+    
+    //
+    // stop chip
+    //
+    HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
+    HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16 | FLEXCAN_MCR_HALT);  
+    
+    //
+    // deactivate all message buffers - this is mandatory for configuration
+    // of message buffers
+    //
+    for (i = 0; i < 16; ++i)
+    {
+        HAL_WRITE_UINT16(&flexcan->mbox[i], MBOX_RXCODE_NOT_ACTIVE);
+    }
+    //
+    // mask all interrupts
+    //
+    HAL_WRITE_UINT16(&flexcan->IMASK, 0x0000);
+    HAL_READ_UINT8(&flexcan->CANCTRL0, tmp8);
+    HAL_WRITE_UINT8(&flexcan->CANCTRL0, tmp8 & ~(FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));
+                      
+    flexcan_set_baud(chan, config->baud);
+    
+    //
+    // setup bus arbitration mode - the LBUF bit defines the 
+    // transmit-first scheme 0 = message buffer with lowest ID
+    // 1 = message buffer with lowest number. We use lowest ID here
+    //
+    HAL_READ_UINT8(&flexcan->CANCTRL1, tmp8);
+    HAL_WRITE_UINT8(&flexcan->CANCTRL1, (tmp8 & ~FLEXCAN_CTRL1_LBUF));
+        
+    info->mbox_alloc_flags = 0; // no buffers used yet
+    
+    //
+    // Message box 14 is our receiv message box. We configure it for
+    // reception of any message
+    //
+    flexcan_cfg_mbox_rx(&flexcan->mbox[info->rx_mbox.num], 0x100, 0);
+    flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, 0, 0);
+    info->mbox_alloc_flags |= (0x0001 << info->rx_mbox.num); // mark rx mbox flag as used
+    info->mbox_alloc_flags |= (0x0001 << info->tx_mbox.num); // mark tx mbox flag as used
+    
+    //
+    // enable the rx interrupt for mbox 0 (tx interrupt are enabled in start xmit)
+    // bus off interrupt and error interrupt
+    //
+    HAL_WRITE_UINT16(&flexcan->IMASK, (0x0001 << info->rx_mbox.num));
+    HAL_READ_UINT8(&flexcan->CANCTRL0, tmp8);
+    HAL_WRITE_UINT8(&flexcan->CANCTRL0, tmp8 | (FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));
+    
+    //
+    // now we can start the chip
+    //
+    flexcan_start_chip(chan);
+    
+    //
+    // store new config values
+    //
+    if (config != &chan->config) 
+    {
+        chan->config = *config;
+    }
+    
+    return true;
+}
+
+//===========================================================================
+//                           CAN INIT
+//
+/// First initialisation and reset of CAN modul.
+//===========================================================================
+static bool flexcan_init(struct cyg_devtab_entry* devtab_entry)
+{
+    can_channel  *chan    = (can_channel*)devtab_entry->priv;
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+
+    if (!flexcan_config(chan, &chan->config, true))
+    {
+        return false;
+    }
+    
+    //
+    // prepare message box interrupt for message box 0 - the rx message box
+    //
+    cyg_drv_interrupt_create(info->rx_mbox.isr_vec,
+                             info->rx_mbox.isr_priority,
+                             (cyg_addrword_t) chan,
+                             &flexcan_mbox_rx_isr,
+                             &flexcan_mbox_rx_dsr,
+                             &(info->rx_mbox.interrupt_handle),
+                             &(info->rx_mbox.interrupt));
+    cyg_drv_interrupt_attach(info->rx_mbox.interrupt_handle);
+    cyg_drv_interrupt_unmask(info->rx_mbox.isr_vec);
+    
+    //
+    // prepare message box interrupt for message box 15 - the tx message box
+    //
+    cyg_drv_interrupt_create(info->tx_mbox.isr_vec,
+                             info->tx_mbox.isr_priority,
+                             (cyg_addrword_t) chan,
+                             &flexcan_mbox_tx_isr,
+                             &flexcan_mbox_tx_dsr,
+                             &(info->tx_mbox.interrupt_handle),
+                             &(info->tx_mbox.interrupt));
+    cyg_drv_interrupt_attach(info->tx_mbox.interrupt_handle);
+    cyg_drv_interrupt_unmask(info->tx_mbox.isr_vec);
+    
+    //
+    // prepare error interrupt
+    //
+    cyg_drv_interrupt_create(info->err_int.isr_vec,
+                             info->err_int.isr_priority,
+                             (cyg_addrword_t) chan,
+                             &flexcan_err_isr,
+                             &flexcan_err_dsr,
+                             &(info->err_int.interrupt_handle),
+                             &(info->err_int.interrupt));
+    cyg_drv_interrupt_attach(info->err_int.interrupt_handle);
+    cyg_drv_interrupt_unmask(info->err_int.isr_vec);
+    
+    //
+    // prepare busoff interrupt
+    //
+    cyg_drv_interrupt_create(info->boff_int.isr_vec,
+                             info->boff_int.isr_priority,
+                             (cyg_addrword_t) chan,
+                             &flexcan_busoff_isr,
+                             &flexcan_busoff_dsr,
+                             &(info->boff_int.interrupt_handle),
+                             &(info->boff_int.interrupt));
+    cyg_drv_interrupt_attach(info->boff_int.interrupt_handle);
+    cyg_drv_interrupt_unmask(info->boff_int.isr_vec);
+        
+    return true;
+}
+
+
+//===========================================================================
+// Flexcan error interrupt handler
+//===========================================================================
+static cyg_uint32  flexcan_err_isr(cyg_vector_t vec, cyg_addrword_t data)
+{
+    can_channel  *chan    = (can_channel *)data;
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint8     ctrl0;
+    cyg_uint16    estat;
+    
+    //
+    // first we disable error interrupts - DSR will reenable it later
+    //
+    HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
+    HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 & ~FLEXCAN_CTRL0_ERRMASK);
+    
+    //
+    // for clearing the interrupt we first read the flag register as 1
+    // and then write it as 1 (and not as zero like the manual stated)
+    // we clear only the flag of this interrupt and leave all other
+    // message box interrupts untouched
+    //
+    HAL_READ_UINT16(&flexcan->ESTAT, estat);
+    HAL_WRITE_UINT16(&flexcan->ESTAT, FLEXCAN_ESTAT_ERRINT); 
+    
+    //
+    // On the mcf5272 there is no need to acknowledge internal
+    // interrupts, only external ones.
+    // cyg_drv_interrupt_acknowledge(vec);
+    //
+    return CYG_ISR_CALL_DSR;
+}
+
+
+//===========================================================================
+// DSR for all interrupts that are no message box interrupts
+//===========================================================================
+static void flexcan_err_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
+{
+    can_channel  *chan     = (can_channel *)data;
+    flexcan_info *info     = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan  = (flexcan_regs *)info->base;
+    cyg_uint8     ctrl0;
+    cyg_uint8     event_id = FLEXCAN_ERR_EVENT;
+
+    //
+    // signal CAN event to generic IO CAN driver - it will do any further 
+    // processing
+    //            
+    chan->callbacks->rcv_event(chan, &event_id);
+    
+    //
+    // reenable bus off interrupts
+    //
+    HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
+    HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 | FLEXCAN_CTRL0_ERRMASK);
+}
+
+
+//===========================================================================
+// Bus off interrupt handler
+//===========================================================================
+static cyg_uint32  flexcan_busoff_isr(cyg_vector_t vec, cyg_addrword_t data)
+{
+    can_channel  *chan    = (can_channel *)data;
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint8     ctrl0;
+    cyg_uint16    estat;
+    
+    //
+    // first we disable bus off interrupts - DSR will reenable it later
+    //
+    HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
+    HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 & ~FLEXCAN_CTRL0_BOFFMSK);
+    
+    //
+    // for clearing the interrupt we first read the flag register as 1
+    // and then write it as 1 (and not as zero like the manual stated)
+    // we clear only the flag of this interrupt and leave all other
+    // message box interrupts untouched
+    //
+    HAL_READ_UINT16(&flexcan->ESTAT, estat);
+    HAL_WRITE_UINT16(&flexcan->ESTAT, FLEXCAN_ESTAT_BOFFINT);  
+    
+    //
+    // On the mcf5272 there is no need to acknowledge internal
+    // interrupts, only external ones.
+    // cyg_drv_interrupt_acknowledge(vec);
+    //
+    return CYG_ISR_CALL_DSR;
+}
+
+
+//===========================================================================
+// DSR for all interrupts that are no message box interrupts
+//===========================================================================
+static void flexcan_busoff_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
+{
+    can_channel  *chan     = (can_channel *)data;
+    flexcan_info *info     = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan  = (flexcan_regs *)info->base;
+    cyg_uint8     ctrl0;
+    cyg_uint8     event_id = FLEXCAN_BUSOFF_EVENT;
+
+    //
+    // signal CAN event to generic IO CAN driver - it will do any further 
+    // processing
+    //            
+    chan->callbacks->rcv_event(chan, &event_id);
+    
+    //
+    // reenable bus off interrupts
+    //
+    HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
+    HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 | FLEXCAN_CTRL0_BOFFMSK);  
+}
+
+
+//===========================================================================
+// Flexcan message box isr
+//===========================================================================
+static cyg_uint32 flexcan_mbox_rx_isr(cyg_vector_t vec, cyg_addrword_t data)
+{
+    can_channel  *chan    = (can_channel *)data;
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16    iflag;
+    cyg_uint16    imask;
+    
+    //
+    // number of message box can be calculated from vector that cause
+    // interrupt - we pass this message box number as additional data to the
+    // callback because it is required in the receive event function later
+    //
+    cyg_uint8 mbox = vec - info->isr_vec_mbox0;    
+    
+    //
+    // first we disable interrupts of this message box - the DSR will
+    // reenable it later
+    //
+    HAL_READ_UINT16(&flexcan->IMASK, imask);
+    HAL_WRITE_UINT16(&flexcan->IMASK, imask & ~(0x0001 << mbox));
+    
+    //
+    // for clearing the interrupt we first read the flag register as 1
+    // and then write it as 1 (and not as zero like the manual stated)
+    // we clear only the flag of this interrupt and leave all other
+    // message box interrupts untouched
+    //
+    HAL_READ_UINT16(&flexcan->IFLAG, iflag);
+    HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));    
+    
+    //
+    // On the mcf5272 there is no need to acknowledge internal
+    // interrupts, only external ones.
+    // cyg_drv_interrupt_acknowledge(vec);
+    //
+    return CYG_ISR_CALL_DSR;
+}
+
+
+//===========================================================================
+// Flexcan message box dsr
+//===========================================================================
+static void flexcan_mbox_rx_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
+{
+    can_channel  *chan    = (can_channel *)data;
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16    imask;
+    
+    //
+    // number of message box can be calculated from vector that caused
+    // interrupt - we pass this message box number as additional data to the
+    // callback
+    //
+    cyg_uint8 mbox = vec - info->isr_vec_mbox0;    
+    
+    //
+    // signal CAN event to generic IO CAN driver - it will do any further 
+    // processing
+    //            
+    chan->callbacks->rcv_event(chan, &mbox);
+    
+    //
+    // reenable interrupts for the message box that caused the DSR to run
+    //
+    HAL_READ_UINT16(&flexcan->IMASK, imask);
+    HAL_WRITE_UINT16(&flexcan->IMASK, imask | (0x0001 << mbox)); 
+}
+
+//===========================================================================
+// Flexcan message box isr
+//===========================================================================
+static cyg_uint32 flexcan_mbox_tx_isr(cyg_vector_t vec, cyg_addrword_t data)
+{
+    can_channel  *chan    = (can_channel *)data;
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16    iflag;
+    cyg_uint16    imask;
+    
+    // number of message box can be calculated from vector that cause
+    // interrupt - we pass this message box number as additional data to the
+    // callback
+    //
+    cyg_uint8 mbox = vec - info->isr_vec_mbox0;
+    
+    //
+    // the first thing we do here is to disable this message box. we do this
+    // because if we just sent a remote transmission request with this message
+    // box then the FLEXCAN modul will automatically set up this message box
+    // for reception of the requested data frame. But we won't receive messages
+    // with the TX message box and deactivate it here immediatelly.
+    // 
+    HAL_WRITE_UINT8(&flexcan->mbox[mbox].ctrlstat, MBOX_TXCODE_NOT_READY);   
+    
+    //
+    // first we disable interrupts of this message box - the DSR will
+    // reenable it later
+    //
+    HAL_READ_UINT16(&flexcan->IMASK, imask);
+    HAL_WRITE_UINT16(&flexcan->IMASK, imask & ~(0x0001 << mbox));
+    
+    //
+    // for clearing the interrupt we first read the flag register as 1
+    // and then write it as 1 (and not as zero like the manual stated)
+    // we clear only the flag of this interrupt and leave all other
+    // message box interrupts untouched
+    //
+    HAL_READ_UINT16(&flexcan->IFLAG, iflag);
+    HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox)); 
+    info->tx_busy = false;   
+    
+    //
+    // On the mcf5272 there is no need to acknowledge internal
+    // interrupts, only external ones.
+    // cyg_drv_interrupt_acknowledge(vec);
+    //
+    return CYG_ISR_CALL_DSR;
+}
+
+
+//===========================================================================
+// Flexcan message box dsr
+//===========================================================================
+static void flexcan_mbox_tx_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
+{
+    can_channel  *chan    = (can_channel *)data;
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16    imask;
+    
+    //
+    // number of message box can be calculated from vector that caused
+    // interrupt - we pass this message box number as additional data to the
+    // callback
+    //
+    cyg_uint8 mbox = vec - info->isr_vec_mbox0;    
+    
+    //
+    // send next message 
+    //            
+    chan->callbacks->xmt_msg(chan, &mbox);
+    
+    //
+    // reenable interrupts for the message box that caused the DSR to run
+    //
+    HAL_READ_UINT16(&flexcan->IMASK, imask);
+    HAL_WRITE_UINT16(&flexcan->IMASK, imask | (0x0001 << mbox));
+}
+
+
+//===========================================================================
+//                     START FLEXCAN MODUL
+//===========================================================================
+static void flexcan_start_chip(can_channel *chan)
+{
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    
+    cyg_uint16 tmp16;
+    HAL_READ_UINT16(&flexcan->CANMCR, tmp16);    
+    HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16 
+                 & ~(FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT));
+}
+
+
+//===========================================================================
+//                      SET ACCEPTANCE MASK
+//===========================================================================
+static void flexcan_set_acceptance_mask(cyg_uint16 *rxmask_reg, cyg_uint32 mask, cyg_uint8 ext)
+{
+    cyg_uint16 id;
+    //
+    // 32 bit access to RXMASK filters is broken so we use  16 Bit
+    // access here
+    //
+    if (ext != 0)
+    {
+        id  = ((mask >> 13) & 0xFFE0);       // set mask bits 18 - 28
+        id |= ((mask >> 15) & 0x7);          // set mask bits 15 -17
+        HAL_WRITE_UINT16(&rxmask_reg[0], id);
+        
+        id = (mask << 1) & 0xFFFE;
+        HAL_WRITE_UINT16(&rxmask_reg[1], id);
+    }
+    else
+    {
+        id = ((mask << 5) & 0xFFE0); 
+        HAL_WRITE_UINT16(&rxmask_reg[0], id);
+        HAL_WRITE_UINT16(&rxmask_reg[1], 0xFFFF);  
+    }
+    
+}
+
+
+
+//===========================================================================
+//                 CONFIGURE MESSAGE BOX FOR TRANSMISSION
+//===========================================================================
+static bool flexcan_cfg_mbox_tx(flexcan_mbox     *pmbox,
+                                cyg_can_message  *pmsg,
+                                bool              rtr)
+{
+    cyg_uint16 id;
+  
+    HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_TXCODE_NOT_READY); 
+    
+    if (pmsg->ext != 0)
+    { 
+        id  = ((pmsg->id >> 13) & 0xFFE0);   // setup id bits 18 - 28
+        id |= (MBOX_CFG_IDE | MBOX_CFG_SSR); // set SSR and IDE bit to 1
+        id |= ((pmsg->id >> 15) & 0x7);      // set id bits 15 - 17
+        HAL_WRITE_UINT16(&pmbox->id_hi, id);
+        
+        id = ((pmsg->id << 1) & 0xFFFE);
+        
+        if (pmsg->rtr)
+        {
+            id |= MBOX_CFG_RTR_EXT;
+        }   
+        
+        HAL_WRITE_UINT16(&pmbox->id_lo, id);
+    }   
+    else
+    {
+        id = ((pmsg->id << 5) & 0xFFE0);
+        if (pmsg->rtr)
+        {
+            id |= MBOX_CFG_RTR_STD;           // set rtr bit for standard ID
+        }
+        HAL_WRITE_UINT16(&pmbox->id_hi, id);
+        HAL_WRITE_UINT16(&pmbox->id_lo, 0);
+    }
+    
+    pmsg->dlc %= 9; // limit data length to 8 bytes
+    
+    //
+    // Now copy data bytes into buffer and start transmission
+    //
+    HAL_WRITE_UINT8_VECTOR(&pmbox->data, pmsg->data, pmsg->dlc, 1); 
+    
+    if (rtr)
+    {
+        HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_TXCODE_RESPONSE | pmsg->dlc);
+    }
+    else
+    {
+        HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_TXCODE_TRANSMIT | pmsg->dlc);
+    }
+    
+    return true;
+}
+
+
+
+//===========================================================================
+//              CONFIGURE MESSAGE BOX FOR RECEPTION OF FRAMES
+//===========================================================================
+static void flexcan_cfg_mbox_rx(flexcan_mbox *pmbox,
+                                cyg_uint32    canid,
+                                cyg_uint8     ext)
+{
+    cyg_uint16 id;
+    
+    HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_NOT_ACTIVE); 
+    
+    if (ext != 0)
+    { 
+        id  = ((canid >> 13) & 0xFFE0);      // setup id bits 18 - 28
+        id |= (MBOX_CFG_IDE | MBOX_CFG_SSR); // set SSR and IDE bit to 1
+        id |= ((canid >> 15) & 0x7);         // set id bits 15 - 17
+        HAL_WRITE_UINT16(&pmbox->id_hi, id);  // write ID high
+        
+        id = ((canid << 1) & 0xFFFE);
+        
+        HAL_WRITE_UINT16(&pmbox->id_lo, id);// write ID low
+    }   
+    else
+    {
+        id = ((canid << 5) & 0xFFE0);
+
+        HAL_WRITE_UINT16(&pmbox->id_hi, id);
+        HAL_WRITE_UINT16(&pmbox->id_lo, 0);
+    }
+    
+    HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_EMPTY);
+}
+
+
+//===========================================================================
+//                       READ DATA FROM MESSAGE BOX
+//==========================================================================
+static void flexcan_read_from_mbox(can_channel  *chan,
+                            cyg_uint8            mbox,
+                            cyg_can_event       *pevent,
+                            cyg_uint8           *ctrlstat)
+{
+    flexcan_info    *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs    *flexcan = (flexcan_regs *)info->base;
+    flexcan_mbox    *pmbox   = &flexcan->mbox[mbox];
+    cyg_can_message *pmsg    = &pevent->msg;
+    cyg_uint16       id;
+    cyg_uint8        i;
+    
+    HAL_READ_UINT8(&pmbox->ctrlstat, *ctrlstat); // this read will lock the mbox
+    
+    //
+    // If message buffer is busy then it is now beeing filled with a new message
+    // This condition will be cleared within 20 cycles - wi simply do a 20 us
+    // delay here, that should be enougth
+    //
+    if (*ctrlstat & MBOX_RXCODE_BUSY)
+    {
+        HAL_DELAY_US(20);
+    }
+    
+    pmsg->dlc = (*ctrlstat & MBOX_CFG_DLC_MASK); // store received data len
+    pmsg->rtr = 0;
+    
+    HAL_READ_UINT16(&pmbox->id_hi, id);         // read ID high
+    
+    if (id & MBOX_CFG_IDE)
+    {
+        pmsg->ext = 1;
+        pmsg->id  = (id & 0xFFE0) << 13;
+        
+        HAL_READ_UINT16(&pmbox->id_lo, id);
+        pmsg->id |= (id & 0xFFFE) >> 1;
+    }
+    else
+    {
+        pmsg->ext = 0;
+        pmsg->id  = (id & 0xFFE0) >> 5;
+    }
+    
+    //
+    // now finally copy data
+    //
+    HAL_READ_UINT8_VECTOR(&pmbox->data, pmsg->data, pmsg->dlc, 1);
+       
+    //
+    // now zero out the remaining bytes in can message in order
+    // to deliver a defined state
+    //
+    for (i = pmsg->dlc; i < 8; ++i)
+    {
+        pmsg->data[i] = 0;
+    }
+  
+    //
+    // now mark this mbox as empty and read the free running timer
+    // to unlock this mbox
+    //
+    HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_EMPTY);
+    HAL_READ_UINT16(&flexcan->TIMER, id);
+#ifdef CYGOPT_IO_CAN_SUPPORT_TIMESTAMP    
+    pevent->timestamp = id;
+#endif
+}
+
+
+//===========================================================================
+//                           INIT CAN BAUD RATE
+//===========================================================================
+static bool flexcan_set_baud(can_channel *chan, cyg_uint16 baud)
+{
+    flexcan_info             *info = (flexcan_info *)chan->dev_priv;
+    flexcan_regs             *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16                mcr_bck;
+    cyg_uint8                 tmp8;
+    cyg_uint8                 presdiv;
+    cyg_uint8                 propseg;
+    cyg_uint8                 pseg1_2;
+    cyg_uint16                baudrate = flexcan_baud_rates[baud];
+    
+    //
+    // Get bit timings from HAL because bit timings depend on sysclock
+    //
+    HAL_MCF52xx_FLEXCAN_GET_BIT_TIMINGS(&baudrate, &presdiv, &propseg, &pseg1_2);
+    
+    //
+    // return false if baudrate is not supported
+    //
+    if (0 == baudrate)
+    {
+        return false;
+    }
+    
+    //
+    // For setting the bit timings we have to stop the flexcan modul
+    //
+    HAL_READ_UINT16(&flexcan->CANMCR, mcr_bck);
+    HAL_WRITE_UINT16(&flexcan->CANMCR, mcr_bck | FLEXCAN_MCR_HALT);
+    
+    //
+    // now we setup bit timings
+    //
+    HAL_WRITE_UINT8(&flexcan->PRESDIV, presdiv);
+    HAL_READ_UINT8(&flexcan->CANCTRL1, tmp8);
+    HAL_WRITE_UINT8(&flexcan->CANCTRL1, (tmp8 & 0xF8) | propseg); 
+    HAL_READ_UINT8(&flexcan->CANCTRL2, tmp8);
+    HAL_WRITE_UINT8(&flexcan->CANCTRL2, (tmp8 & 0xC0) | pseg1_2); 
+    
+    //
+    // Now restore the previous state - if the modul was started then
+    // it will no be started again, if it was stopped, then it remains stopped
+    //
+    HAL_WRITE_UINT16(&flexcan->CANMCR, mcr_bck);
+    
+    return true;
+}
+
+//---------------------------------------------------------------------------
+// end of can_mcf_flexcan.c
+
new file mode 100644
--- /dev/null
+++ b/packages/devs/can/m68k/mcf52xx/current/tests/can_test_aux.inl
@@ -0,0 +1,144 @@
+//==========================================================================
+//
+//        can_test_aux.inl
+//
+//        CAN test auxiliary functions
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     Uwe Kindler
+// Contributors:  Uwe Kindler
+// Date:          2005-08-07
+// Description:   Auxiliary functions for CAN driver tests
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+//                           PRINT CAN EVENT
+//===========================================================================
+void print_can_msg(cyg_can_message *pmsg, char *pMsg)
+{   
+    char *pmsg_str;
+    static char* msg_tbl[] =
+    {
+        "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:]\n",
+        "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X]\n",
+        "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X]\n",
+        "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X]\n",
+        "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X]\n",
+        "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X %02X]\n",
+        "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X %02X %02X]\n",
+        "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X %02X %02X %02X]\n",
+        "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X %02X %02X %02X %02X]\n"
+    };
+    
+    if (pmsg->rtr)
+    {
+        diag_printf("%s [ID:%03X] [RTR:%d] [EXT:%d]\n",
+                    pMsg,
+                    pmsg->id,
+                    pmsg->rtr,
+                    pmsg->ext);
+                    
+        return;
+    }
+    
+    if (pmsg->dlc > 8)
+    {
+        pmsg_str = msg_tbl[8];
+    }   
+    else
+    {
+        pmsg_str = msg_tbl[pmsg->dlc];
+    } 
+    
+    diag_printf(pmsg_str,
+                pMsg,
+                pmsg->id,
+                pmsg->rtr,
+                pmsg->ext,
+                pmsg->data[0],
+                pmsg->data[1],
+                pmsg->data[2],
+                pmsg->data[3],
+                pmsg->data[4],
+                pmsg->data[5],
+                pmsg->data[6],
+                pmsg->data[7]);
+}
+
+
+//===========================================================================
+//                         PRINT CAN EVENT FLAGS
+//===========================================================================
+void print_can_flags(cyg_uint16 flags, char *pMsg)
+{
+    char      *pmsg_str;
+    cyg_uint8  i ;
+    static char* msg_tbl[] =
+    {
+        "RX  ",
+        "TX  ",
+        "WRX  ",
+        "WTX  ",
+        "ERRP  ",
+        "BOFF  ",
+        "OVRX  ",
+        "OVTX  ",
+        "CERR  ",
+        "LSTY  ",
+        "ESTY  ",
+        "ALOS  ",
+        "DEVC  ",
+    };
+    i = 0;
+    while (flags && (i < 16))
+    {
+        if (flags & 0x0001)
+        {
+            pmsg_str = msg_tbl[i];
+            diag_printf(pmsg_str);
+        }
+        flags >>=1;
+        i++;
+    }
+    
+    diag_printf("\n");
+}
+
+//---------------------------------------------------------------------------
+// end of can_test_aux.inl
new file mode 100644
--- /dev/null
+++ b/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_load.c
@@ -0,0 +1,294 @@
+//==========================================================================
+//
+//        flexcan_load.c
+//
+//        FlexCAN load test
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     Uwe Kindler
+// Contributors:  Uwe Kindler
+// Date:          2005-08-14
+// Description:   FlexCAN load test
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+//                                INCLUDES
+//===========================================================================
+#include <pkgconf/system.h>
+
+#include <cyg/infra/testcase.h>         // test macros
+#include <cyg/infra/cyg_ass.h>          // assertion macros
+#include <cyg/infra/diag.h>
+
+// Package requirements
+#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL)
+
+#include <pkgconf/kernel.h>
+#include <cyg/io/io.h>
+#include <cyg/io/canio.h>
+
+// Package option requirements
+#if defined(CYGFUN_KERNEL_API_C)
+
+#include <cyg/hal/hal_arch.h>           // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/kernel/kapi.h>
+
+
+//===========================================================================
+//                               DATA TYPES
+//===========================================================================
+typedef struct st_thread_data
+{
+    cyg_thread   obj;
+    long         stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+    cyg_handle_t hdl;
+} thread_data_t;
+
+
+//===========================================================================
+//                              LOCAL DATA
+//===========================================================================
+cyg_thread_entry_t can0_thread;
+thread_data_t      can0_thread_data;
+
+cyg_thread_entry_t can1_thread;
+thread_data_t      can1_thread_data;
+
+cyg_io_handle_t    hDrvFlexCAN;
+
+
+//===========================================================================
+//                          LOCAL FUNCTIONS
+//===========================================================================
+#include "can_test_aux.inl" // include CAN test auxiliary functions
+
+
+//===========================================================================
+//                             READER THREAD 
+//===========================================================================
+void can0_thread(cyg_addrword_t data)
+{
+    cyg_uint32             len;
+    cyg_can_event          rx_event;
+    cyg_can_timeout_info_t timeouts;
+
+#if defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS)   
+    //
+    // setup large timeout values because we do not need timeouts here
+    //
+    timeouts.rx_timeout = 100000;
+    timeouts.tx_timeout = 100000;
+    
+    len = sizeof(timeouts);
+    if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_TIMEOUT ,&timeouts, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0");
+    }
+#endif // defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS)  
+    
+    //
+    // This thread simply receives all CAN events and prints the event flags and the
+    // CAN message if it was a TX or RX event. You can use this test in order to check
+    // when a RX overrun occurs
+    //
+    while (1)
+    {
+        len = sizeof(rx_event); 
+            
+        if (ENOERR != cyg_io_read(hDrvFlexCAN, &rx_event, &len))
+        {
+            CYG_TEST_FAIL_FINISH("Error reading from /dev/can0");
+        }
+        else
+        {
+            print_can_flags(rx_event.flags, "");
+            
+            if ((rx_event.flags & CYGNUM_CAN_EVENT_RX) || (rx_event.flags & CYGNUM_CAN_EVENT_TX))
+            {
+                print_can_msg(&rx_event.msg, "");
+            }
+        }    
+    }             
+}
+
+
+//===========================================================================
+//                            WRITER THREAD
+//===========================================================================
+void can1_thread(cyg_addrword_t data)
+{
+    cyg_uint16      i = 0;
+    cyg_uint32      len;
+    cyg_can_message tx_msg =
+    {
+        0x000,                                               // CAN identifier
+        {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7},    // 8 data bytes
+        CYGNUM_CAN_ID_STD,                                   // standard frame
+        CYGNUM_CAN_FRAME_DATA,                               // data frame
+        8,                                                   // data length code
+    };
+    
+    //
+    // This thread simply sends CAN messages. It increments the ID for each new CAN messsage
+    // and sends a remote frame after seven data frames. In the first byte of each data frame
+    // the number (0 - 7) of the data frame is stored and the length of the data frame grows
+    // from 1 - 8 data bytes.
+    //
+    // The received pattern should look like this way:
+    // ID    Length    Data
+    // ----------------------------------------------
+    // 000   1         00
+    // 001   2         01 F1
+    // 002   3         02 F1 F2
+    // 003   4         03 F1 F2 F3
+    // 004   5         04 F1 F2 F3 F4
+    // 005   6         05 F1 F2 F3 F4 F5
+    // 006   7         06 F1 F2 F3 F4 F5 F6
+    // 007   8         Remote Request
+    // 008   1         00
+    // 009   2         01 F1
+    // 00A   3         02 F1 F2
+    // ...
+    //
+    while (1)
+    {
+        tx_msg.id      = i;
+        tx_msg.dlc     = (i % 8) + 1;
+        tx_msg.data[0] = (i % 8);
+        i = (i + 1) % 0x7FF;
+        
+        //
+        // we send a remote frame after 7 data frames
+        //
+        if (!(i % 8))
+        {
+            tx_msg.rtr = CYGNUM_CAN_FRAME_RTR;
+        }
+        else
+        {
+            tx_msg.rtr = CYGNUM_CAN_FRAME_DATA;
+        }
+        
+        len = sizeof(tx_msg);
+        if (ENOERR != cyg_io_write(hDrvFlexCAN, &tx_msg, &len))
+        {
+            CYG_TEST_FAIL_FINISH("Error writing to /dev/can0");
+        }
+        else
+        {
+            print_can_msg(&tx_msg, "TX: ");
+        } 
+        
+        cyg_thread_delay(100);          
+    } // while (1)
+}
+
+
+
+void
+cyg_start(void)
+{
+    cyg_uint32     len;
+    cyg_can_info_t can_cfg;
+    
+    CYG_TEST_INIT();
+    
+    //
+    // open flexcan device driver
+    //
+    if (ENOERR != cyg_io_lookup("/dev/can0", &hDrvFlexCAN)) 
+    {
+        CYG_TEST_FAIL_FINISH("Error opening /dev/can0");
+    }
+    
+    //
+    // setup CAN baudrate 250 KBaud
+    //
+    can_cfg.baud = CYGNUM_CAN_KBAUD_250;
+    len = sizeof(can_cfg);
+    if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_INFO ,&can_cfg, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0");
+    }
+    
+    //
+    // create the two threads which access the CAN device driver
+    // a reader thread with a higher priority and a writer thread
+    // with a lower priority
+    //
+    cyg_thread_create(4, can0_thread, 
+                        (cyg_addrword_t) 0,
+		                "can0_thread", 
+		                (void *) can0_thread_data.stack, 
+		                1024 * sizeof(long),
+		                &can0_thread_data.hdl, 
+		                &can0_thread_data.obj);
+		                
+    cyg_thread_create(5, can1_thread, 
+                        (cyg_addrword_t) can0_thread_data.hdl,
+		                "can1_thread", 
+		                (void *) can1_thread_data.stack, 
+		                1024 * sizeof(long),
+		                &can1_thread_data.hdl, 
+		                &can1_thread_data.obj);
+		                
+    cyg_thread_resume(can0_thread_data.hdl);
+    cyg_thread_resume(can1_thread_data.hdl);
+    
+    cyg_scheduler_start();
+}
+
+#else // CYGFUN_KERNEL_API_C
+#define N_A_MSG "Needs kernel C API"
+#endif
+
+#else // CYGPKG_IO_CAN && CYGPKG_KERNEL
+#define N_A_MSG "Needs IO/CAN and Kernel"
+#endif
+
+#ifdef N_A_MSG
+void
+cyg_start( void )
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA( N_A_MSG);
+}
+#endif // N_A_MSG
+
+// EOF flexcan_load.c
new file mode 100644
--- /dev/null
+++ b/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_remote.c
@@ -0,0 +1,233 @@
+//==========================================================================
+//
+//        flexcan_remote.c
+//
+//        FlexCAN remote response buffer test
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     Uwe Kindler
+// Contributors:  Uwe Kindler
+// Date:          2005-08-14
+// Description:   FlexCAN load test
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+//                                INCLUDES
+//===========================================================================
+#include <pkgconf/system.h>
+
+#include <cyg/infra/testcase.h>         // test macros
+#include <cyg/infra/cyg_ass.h>          // assertion macros
+#include <cyg/infra/diag.h>
+
+// Package requirements
+#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL)
+
+#include <pkgconf/kernel.h>
+#include <cyg/io/io.h>
+#include <cyg/io/canio.h>
+
+// Package option requirements
+#if defined(CYGFUN_KERNEL_API_C)
+
+#include <cyg/hal/hal_arch.h>           // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/kernel/kapi.h>
+
+
+//===========================================================================
+//                               DATA TYPES
+//===========================================================================
+typedef struct st_thread_data
+{
+    cyg_thread   obj;
+    long         stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+    cyg_handle_t hdl;
+} thread_data_t;
+
+
+//===========================================================================
+//                              LOCAL DATA
+//===========================================================================
+cyg_thread_entry_t can0_thread;
+thread_data_t      can0_thread_data;
+
+
+cyg_io_handle_t    hDrvFlexCAN;
+
+
+//===========================================================================
+//                          LOCAL FUNCTIONS
+//===========================================================================
+#include "can_test_aux.inl" // include CAN test auxiliary functions
+
+
+//===========================================================================
+//                             READER THREAD 
+//===========================================================================
+void can0_thread(cyg_addrword_t data)
+{
+    cyg_uint32             len;
+    cyg_can_event          rx_event;
+    cyg_can_rtr_buf_t      rtr_buf;
+    cyg_can_rtr_buf_t      rtr_buf2;
+
+   
+    rtr_buf.handle      = CYGNUM_CAN_RTR_BUF_INIT;
+    rtr_buf.msg.id      = 0x7FF;
+    rtr_buf.msg.ext     = CYGNUM_CAN_ID_STD;
+    rtr_buf.msg.rtr     = CYGNUM_CAN_FRAME_DATA;
+    rtr_buf.msg.dlc     = 1;
+    rtr_buf.msg.data[0] = 0xAB;
+    
+    len = sizeof(rtr_buf);
+    if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_RTR_BUF ,&rtr_buf, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0");
+    } 
+    
+    if (rtr_buf.handle == CYGNUM_CAN_RTR_BUF_NA)
+    {
+        CYG_TEST_FAIL_FINISH("No free message buffer available for /dev/can0");
+    }
+    
+    rtr_buf2.handle      = CYGNUM_CAN_RTR_BUF_INIT;
+    rtr_buf2.msg.id      = 0x7FE;
+    rtr_buf2.msg.ext     = CYGNUM_CAN_ID_STD;
+    rtr_buf2.msg.rtr     = CYGNUM_CAN_FRAME_DATA;
+    rtr_buf2.msg.dlc     = 4;
+    rtr_buf2.msg.data[0] = 0xAB;
+    
+    len = sizeof(rtr_buf2);
+    if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_RTR_BUF ,&rtr_buf2, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0");
+    } 
+    
+    if (rtr_buf.handle == CYGNUM_CAN_RTR_BUF_NA)
+    {
+        CYG_TEST_FAIL_FINISH("No free message buffer available for /dev/can0");
+    }
+    
+    diag_printf("Test of FlexCAN remote response buffer configuration\n"
+                "If a CAN node sends a remote request with ID 0x7FE\n"
+                "or 0x7FF then the FlexCAN modul should respond with\n"
+                "data frames.\n");
+    diag_printf("!!! This test can be stopped by sending a data frame with ID 0x100 !!!\n\n");
+    
+    while (1)
+    {
+        len = sizeof(rx_event); 
+            
+        if (ENOERR != cyg_io_read(hDrvFlexCAN, &rx_event, &len))
+        {
+            CYG_TEST_FAIL_FINISH("Error reading from /dev/can0");
+        }
+        
+        if (0x100 == rx_event.msg.id)
+        {
+            CYG_TEST_PASS_FINISH("flexcan_remote test OK"); 
+        }
+    }
+
+              
+}
+
+
+void
+cyg_start(void)
+{
+    cyg_uint32     len;
+    cyg_can_info_t can_cfg;
+    
+    CYG_TEST_INIT();
+    
+    //
+    // open flexcan device driver
+    //
+    if (ENOERR != cyg_io_lookup("/dev/can0", &hDrvFlexCAN)) 
+    {
+        CYG_TEST_FAIL_FINISH("Error opening /dev/can0");
+    }
+    
+    //
+    // setup CAN baudrate 250 KBaud
+    //
+    can_cfg.baud = CYGNUM_CAN_KBAUD_250;
+    len = sizeof(can_cfg);
+    if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_INFO ,&can_cfg, &len))
+    {
+        CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0");
+    }
+    
+    //
+    // create the two threads which access the CAN device driver
+    // a reader thread with a higher priority and a writer thread
+    // with a lower priority
+    //
+    cyg_thread_create(4, can0_thread, 
+                        (cyg_addrword_t) 0,
+		                "can0_thread", 
+		                (void *) can0_thread_data.stack, 
+		                1024 * sizeof(long),
+		                &can0_thread_data.hdl, 
+		                &can0_thread_data.obj);
+		                
+    cyg_thread_resume(can0_thread_data.hdl);
+    
+    cyg_scheduler_start();
+}
+
+#else // CYGFUN_KERNEL_API_C
+#define N_A_MSG "Needs kernel C API"
+#endif
+
+#else // CYGPKG_IO_CAN && CYGPKG_KERNEL
+#define N_A_MSG "Needs IO/CAN and Kernel"
+#endif
+
+#ifdef N_A_MSG
+void
+cyg_start( void )
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA( N_A_MSG);
+}
+#endif // N_A_MSG
+
+// EOF flexcan_remote.c
--- a/packages/ecos.db
+++ b/packages/ecos.db
@@ -94,6 +94,33 @@ package CYGPKG_IO_SERIAL {
            serial devices."
 }
 
+package CYGPKG_IO_CAN {
+	alias 		{ "CAN device drivers" can io_can }
+	directory	io/can
+	script		io_can.cdl
+        description "
+           This package contains drivers for basic I/O services on
+           CAN devices."
+}
+
+package CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN {
+    alias             { "MCF52xx FlexCAN device drivers"
+                        devs_can_mcf52xx_flexcan mcf52xx_flexcan_serial_driver }
+    hardware
+    directory	      devs/can/m68k/mcf52xx
+    script	          can_mcf52xx.cdl	
+    description       "Generic CAN device driver for the on-chip
+                       FlexCAN modules in MCF52xx ColdFire processors."
+}
+
+package CYGPKG_IO_CAN_LOOP {
+    alias             { "Loop CAN device drivers"
+                        devs_can_loop loop_can_driver }
+    directory	      devs/can/loop
+    script	      can_loop.cdl	
+    description       "Loopback CAN device driver."
+}
+
 package CYGPKG_IO_PCMCIA {
 	alias 		{ "PCMCIA & Compact Flash support" pcmcia io_pcmcia cf }
 	directory	io/pcmcia
new file mode 100644
--- /dev/null
+++ b/packages/io/can/current/ChangeLog
@@ -0,0 +1,35 @@
+2005-05-24  Uwe Kindler  <uwe_kindler@web.de>
+
+	* Generic CAN driver package created
+
+//===========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2003, 2004 eCosCentric Limited
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
new file mode 100644
--- /dev/null
+++ b/packages/io/can/current/cdl/io_can.cdl
@@ -0,0 +1,179 @@
+# ====================================================================
+#
+#      io_can.cdl
+#
+#      eCos IO configuration data
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+##
+## eCos is free software; you can redistribute it and/or modify it under
+## the terms of the GNU General Public License as published by the Free
+## Software Foundation; either version 2 or (at your option) any later version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+## WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License along
+## with eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+## at http://sources.redhat.com/ecos/ecos-license/
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):      Uwe Kindler
+# Original data:  gthomas
+# Contributors:
+# Date:           2005-05-17
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_IO_CAN {
+    display       "CAN device drivers"
+    active_if     CYGPKG_IO
+    requires      CYGPKG_ERROR
+    include_dir   cyg/io
+    description   "
+        This option enables drivers for basic I/O services on
+        CAN devices."
+    doc           ref/io.html
+
+    compile       -library=libextras.a can.c
+ 
+    define_proc {
+	puts $::cdl_header "/***** proc output start *****/"
+	puts $::cdl_header "#include <pkgconf/system.h>"
+	puts $::cdl_header "#ifdef CYGDAT_IO_CAN_DEVICE_HEADER"
+	puts $::cdl_header "# include CYGDAT_IO_CAN_DEVICE_HEADER"
+	puts $::cdl_header "#endif "
+	puts $::cdl_header "/****** proc output end ******/"
+    }
+
+    cdl_interface CYGINT_IO_CAN_TIMESTAMP {
+        display "CAN driver supports timestamps"
+    }
+    
+    cdl_option CYGOPT_IO_CAN_SUPPORT_TIMESTAMP {
+        display       "Support CAN event timestamps"
+        requires      { CYGINT_IO_CAN_TIMESTAMP > 0 }
+        default_value 0
+        description "
+            If the CAN hardware driver supports some kind of timestamps
+            then this option enables propagation of timestamps to higher layers. 
+            This may add some extra code to hardware drivers."
+    }
+    
+    cdl_option CYGOPT_IO_CAN_TX_EVENT_SUPPORT {
+        display       "Support TX events"
+        default_value 0
+        description "
+            This option enables support for TX events. If a CAN message is
+            transmitted successfully a TX event will be inserted into the
+            receive event queue and propagated to higher layers. If this
+            option is enabled the RX event queue will be filled faster."
+    }
+    
+    cdl_component CYGPKG_IO_CAN_DEVICES {
+        display       "Hardware CAN device drivers"
+        flavor        bool
+        default_value 1
+        description   "
+            This option enables the hardware device drivers
+	        for the current platform."
+    }
+    
+    cdl_option CYGOPT_IO_CAN_SUPPORT_NONBLOCKING {
+        display       "Support non-blocking read and write calls"
+        default_value 0
+        description   "
+            This option enables extra code in the generic CAN driver
+            which allows clients to switch read() and write() call
+            semantics from blocking to non-blocking."
+    }
+    
+    cdl_component CYGOPT_IO_CAN_SUPPORT_TIMEOUTS {
+        display       "Support read/write timeouts"
+        flavor        bool
+        default_value 0
+        active_if     CYGPKG_KERNEL
+        requires      CYGMFN_KERNEL_SYNCH_CONDVAR_TIMED_WAIT
+        requires      CYGOPT_IO_CAN_SUPPORT_NONBLOCKING
+        description   "
+             Read and write operations are blocking calls. If no CAN message
+             arrives for a long time the calling thread remains blocked. If
+             nonblocking calls are enabled but the call should return after 
+             a certain amount of time then this option should be enabled."
+             
+        cdl_option CYGNUM_IO_CAN_DEFAULT_TIMEOUT_READ {
+            display "Default read timeout."
+            flavor  data
+            default_value 100
+            description   "
+                The initial timeout value in clock ticks for cyg_io_read() calls."
+        }
+        
+        cdl_option CYGNUM_IO_CAN_DEFAULT_TIMEOUT_WRITE {
+            display "Default write timeout."
+            flavor  data
+            default_value 100
+            description   "
+                The initial timeout value in clock ticks for cyg_io_write() calls."
+        }
+    }
+
+   cdl_component CYGPKG_IO_CAN_OPTIONS {
+        display "CAN device driver build options"
+        flavor  none
+        description   "
+	    Package specific build options including control over
+	    compiler flags used only in building this package,
+	    and details of which tests are built."
+
+
+        cdl_option CYGPKG_IO_CAN_CFLAGS_ADD {
+            display "Additional compiler flags"
+            flavor  data
+            no_define
+            default_value { "" }
+            description   "
+                This option modifies the set of compiler flags for
+                building the CAN device drivers. These flags are used in addition
+                to the set of global flags."
+        }
+
+        cdl_option CYGPKG_IO_CAN_CFLAGS_REMOVE {
+            display "Suppressed compiler flags"
+            flavor  data
+            no_define
+            default_value { "" }
+            description   "
+                This option modifies the set of compiler flags for
+                building the CAN device drivers. These flags are removed from
+                the set of global flags if present."
+        }
+
+    }
+}
+
+# EOF io_can.cdl
new file mode 100644
--- /dev/null
+++ b/packages/io/can/current/doc/can_driver_doc.html
@@ -0,0 +1,296 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+
+	<head>
+		<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
+		<meta name="generator" content="Adobe GoLive 6">
+		<title>IO/CAN Doc</title>
+	</head>
+
+	<body bgcolor="#ffffff">
+		<h2>CAN driver details</h2>
+		<p>A raw CAN driver is is provided as a standard part of the eCos system. Use the include file <code>&lt;cyg/io/canio.h&gt;</code> for this driver. The CAN driver is capable of sending single CAN messages and receiving single CAN events to a CAN device. Controls are provided to configure the actual hardware, but there is no manipulation of the data by this driver. There may be many instances of this driver in a given system, one for each CAN channel. Each channel corresponds to a physical device and there will typically be a device module created for this purpose. The device modules themselves are configurable, allowing specification of the actual hardware details.</p>
+		<h3>User API</h3>
+		<p>The CAN driver  uses the standard eCos I/O API functions. All functions except <code>cyg_io_lookup()</code> require an I/O &quot;handle&quot;.</p>
+		<p>All functions return a value of the type <code>Cyg_ErrNo</code>. If an error condition is detected, this value will be negative and the absolute value indicates the actual error, as specified in <code>cyg/error/codes.h</code>. The only other legal return value will be <code>ENOERR</code> , <code>-EINTR </code>and<code> -EAGAIN</code>. All other function arguments are pointers (references). This allows the drivers to pass information efficiently, both into and out of the driver. The most striking example of this is the <i>len </i>value passed to the read and write functions. This parameter contains the desired length of data on input to the function and the actual transferred length on return.</p>
+		<h4>Lookup a CAN device</h4>
+		<p><code>Cyg_ErrNo cyg_io_lookup(<br>&nbsp;&nbsp;&nbsp;&nbsp;const char &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*name,<br>&nbsp;&nbsp;&nbsp;&nbsp;cyg_io_handle_t *handle )</code></p>
+		<p>This function maps a device name onto an appropriate handle. If the named device is not in the system, then the error -<code>ENOENT</code> is returned. If the device is found, then the handle for the device is returned by way of the handle pointer <i>*handle</i>.</p>
+		<h4>Send a CAN message</h4>
+		<p><code>Cyg_ErrNo cyg_io_write(<br>
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_io_handle_t &nbsp;handle,<br>
+				&nbsp;&nbsp;&nbsp;&nbsp;const void &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*buf,<br>
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_uint32 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*len )<br>
+			</code></p>
+		<p>This function sends <b>one single</b> CAN message (not a buffer of  CAN messages) to a device. The size of data to send is contained in <i>*len</i> and the actual size sent will be returned in the same place. A pointer to a <code>cyg_can_message</code> is contained in <i>*buf</i> . If a message was sucessfully sent, the function returns <code>ENOERR</code>. If nonblocking calls are supported and the TX buffer is full then the function returns immediatelly with <code>-EAGAIN</code>. If the driver supports timeouts and nonblocking calls are enabled then this function may also return <code>-EINTR</code> after the timout expired and the TX buffer is still full. This is important for applications where i.e. a watchdog need to be toggled by each task. Because it may happen that no CAN message will arrive for a long time the receiving thread remains blocked if the driver does not support timeouts and the watchdog will never be toggled.</p>
+		<p><code>typedef struct can_message<br>
+				{<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_uint32 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id;<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_uint8 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data[8];<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_can_id_type &nbsp;&nbsp;&nbsp;ext;<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_can_frame_type rtr;<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_uint8 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dlc;<br>
+				} cyg_can_message;</code></p>
+		<p>The type <code>cyg_can_message</code> provides a device independent type of CAN message. Before calling the write function this message should be setup properly. The<i> id</i> field contains the 11 Bit or 29 bit CAN message identifier depending on the value of the <i>ext</i> field. The <i>data</i> field contains the 8 data bytes of one CAN message. The <i>ext</i> field configures the type of CAN message identifier (<code>CYGNUM_CAN_ID_STD</code> = standard 11 Bit id,<i> </i><code>CYGNUM_CAN_ID_EXT</code> = extended 29 Bit id). The <i>rtr</i> field contains the frame type. (<code>CYGNUM_CAN_FRAME_DATA</code> = data frame, <code>CYGNUM_CAN_FRAME_RTR</code> = remote transmission request). The <i>dlc</i> field (data length code) contains the number of valid data bytes (0 - 8) in the <i>data</i> field.</p>
+		<p>Example code for sending one single CAN message:</p>
+		<p><code>cyg_can_message tx_msg;<br>cyg_uint32 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;len;<br>
+				Cyg_ErrNo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret;<br>
+				<br>
+				
+				
+				tx_msg.id &nbsp;= 0x100;<br>
+				
+				
+				tx_msg.ext = CYGNUM_CAN_ID_EXT;<br>
+				
+				tx_msg.rtr = CYGNUM_CAN_FRAME_DATA;<br>
+				
+				tx_msg.dlc = 1;<br>
+				
+				tx_msg.data[0] = 0xF1;<br>
+				<br>
+				
+				len = sizeof(tx_msg);<br>
+				ret = cyg_io_write(hDrvCAN, &amp;tx_msg, &amp;len);</code></p>
+		<h4>Read a CAN event</h4>
+		<p><code>Cyg_ErrNo cyg_io_read(<br>
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_io_handle_t &nbsp;handle,<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;void &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*buf,<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_uint32 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*len )<br>
+			</code></p>
+		<p>This function receives one single event from a device. The desired size of data to receive is contained in <i>*len</i> and the actual size obtained will be returned in the same place. A pointer to a<code> cyg_can_event</code> is contained in <i>*buf</i>.  If a message was sucessfully sent, the function returns <code>ENOERR</code>. If nonblocking calls are supported the driver returns <code>-EAGAIN</code> if the RX buffer is empty. If the driver supports timeouts  and nonblocking calls are enabled then this function may also return <code>-EINTR</code> if the timout value expired and the RX buffer is still empty.</p>
+		<p><code>typedef struct cyg_can_event_st<br>
+				{<br>
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_uint32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timestamp;<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_can_message msg;<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_uint16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;flags;<br>
+				} cyg_can_event;<br>
+			</code></p>
+		<p>A <code>cyg_can_event</code>  provides a generic device independent type for handling CAN events that may occur. If the driver supports timestamps then the <i>timestamp</i> field my contain a timestamp value for an event that occured. The <i>msg</i> field contains a CAN message if an RX or TX event occured. The <i>flags</i> field contains 16 bits that indicate which kind of events occured. The following events are supported and after receiving an event the flag field should be checked against these values:</p>
+		<p><code>typedef enum <br>
+				{<br>
+				
+				&nbsp;&nbsp;CYGNUM_CAN_EVENT_RX &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 0x0001, // message received<br>
+				
+				&nbsp;&nbsp;CYGNUM_CAN_EVENT_TX &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 0x0002, // mesage transmitted<br>
+				
+				&nbsp;&nbsp;CYGNUM_CAN_EVENT_WARNING_RX &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 0x0004, // tx error counter (TEC) reached warning level (&gt;96)<br>
+				
+				&nbsp;&nbsp;CYGNUM_CAN_EVENT_WARNING_TX &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 0x0008, // rx error counter (REC) reached warning level (&gt;96)<br>
+				
+				&nbsp;&nbsp;CYGNUM_CAN_EVENT_ERR_PASSIVE &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 0x0010, // CAN &quot;error passive&quot; occured<br>
+				
+				&nbsp;&nbsp;CYGNUM_CAN_EVENT_BUS_OFF &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 0x0020, // CAN &quot;bus off&quot; error occured<br>
+				
+				&nbsp;&nbsp;CYGNUM_CAN_EVENT_OVERRUN_RX &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 0x0040, // overrun in RX queue or hardware occured<br>
+				
+				&nbsp;&nbsp;CYGNUM_CAN_EVENT_OVERRUN_TX &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 0x0080, // overrun in TX queue occured<br>
+				
+				&nbsp;&nbsp;CYGNUM_CAN_EVENT_CAN_ERR &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 0x0100, // a CAN bit or frame error occured<br>
+				
+				&nbsp;&nbsp;CYGNUM_CAN_EVENT_LEAVING_STANDBY &nbsp;= 0x0200, // CAN hardware leaves standby / power don mode or is waked up<br>
+				
+				&nbsp;&nbsp;CYGNUM_CAN_EVENT_ENTERING_STANDBY = 0x0400, // CAN hardware enters standby / power down mode<br>
+				
+				&nbsp;&nbsp;CYGNUM_CAN_EVENT_ARBITRATION_LOST = 0x0800, // arbitration lost<br>
+				
+				&nbsp;&nbsp;CYGNUM_CAN_EVENT_DEVICE_CHANGED &nbsp;&nbsp;= 0x1000, // device changed event<br>
+				} cyg_can_event_flags;</code></p>
+		<p>Often the flags field will contain only one single set flag. But it is possible that a number of flags is set and so the flag field should always be checked by a receiver. I.e. if the <code>CYGNUM_CAN_EVENT_RX </code>is set then also the <code>CYGNUM_CAN_EVENT_OVERRUN_RX </code>may be set if the received message caused an RX overrun.</p>
+		<p>The internal receive buffers of the CAN device driver a circular buffers. That means that even if the buffers are completely filled new messages will be received. In this case the newest message will always overwrite the oldes message in receive buffer. If this happens the <code>CYGNUM_CAN_EVENT_OVERRUN_RX </code>flag will be set for this new message that caused overwriting of the old one. </p>
+		<p>Example code for receiving one single CAN event:</p>
+		<p><code>cyg_can_event rx_event;<br>
+				cyg_uint32 &nbsp;&nbsp;&nbsp;len;<br>
+				Cyg_ErrNo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret;<br>
+				<br>
+				
+				len = sizeof(rx_event);<br>
+				
+				ret = cyg_io_read(hDrvCAN, &amp;rx_event, &amp;len);<br>
+				<br>
+				
+				if (ENOERR == ret)<br>
+				
+				{<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;if (rx_event.flags &amp; CYGNUM_CAN_EVENT_RX)<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;{<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// handle RX event<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;}<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(rx_event.flags &amp; ~CYGNUM_CAN_EVENT_RX)<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;{<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// handle other events<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;}<br>
+				
+				}<br>
+				
+				else if (-EINTR == ret)<br>
+				
+				{<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;// handle timeout<br>
+				
+				}<br>
+			</code></p>
+		<h4>Read configuration of a CAN device</h4>
+		<p><code>Cyg_ErrNo cyg_io_get_config(<br>
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_io_handle_t handle,<br>
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_uint32 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;key,<br>
+				&nbsp;&nbsp;&nbsp;&nbsp;void &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*buf,<br>
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_uint32 &nbsp;&nbsp;&nbsp;&nbsp;*len )<br>
+			</code></p>
+		<p>This function is used to obtain run-time configuration about a device. The type of information retrieved is specified by the key. The data will be returned in the given buffer. The value of <i>*len</i> should contain the amount of data requested, which must be at least as large as the size appropriate to the selected key. The actual size of data retrieved is placed in <i>*len</i>. The appropriate key values are all listed in the file<code> &lt;cyg/io/config_keys.h&gt;</code>.</p>
+		<p>The following config keys are currently supported:</p>
+		<p><code>CYG_IO_GET_CONFIG_READ_BLOCKING<br>
+				CYG_IO_GET_CONFIG_WRITE_BLOCKING<br>
+				CYG_IO_GET_CONFIG_CAN_INFO<br>
+				CYG_IO_GET_CONFIG_CAN_BUFFER_INFO<br>
+				CYG_IO_GET_CONFIG_CAN_TIMEOUT<br>
+			</code></p>
+		<h4>Change configuration of a CAN device</h4>
+		<p><code>Cyg_ErrNo cyg_io_set_config(<br>
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_io_handle_t &nbsp;handle,<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_uint32 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;key,<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;const void &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*buf,<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_uint32 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*len)<br>
+			</code></p>
+		<p>This function is used to manipulate or change the run-time configuration of a device. The type of information is specified by the key. The data will be obtained from the given buffer. The value of <i>*len</i> should contain the amount of data provided, which must match the size appropriate to the selected key. The appropriate key values are all listed in the file <code>&lt;cyg/io/config_keys.h&gt;</code>.</p>
+		<p>The following config keys are currently supported:</p>
+		<p><code>CYG_IO_SET_CONFIG_READ_BLOCKING<br>
+				CYG_IO_SET_CONFIG_WRITE_BLOCKING<br>
+				CYG_IO_SET_CONFIG_CAN_INFO<br>
+				
+				CYG_IO_SET_CONFIG_CAN_TIMEOUT<br>
+				CYG_IO_SET_CONFIG_CAN_RTR_BUF<br>
+			</code></p>
+		<h3>Runtime Configuration</h3>
+		<p>Runtime configuration is achieved by exchanging data structures with the driver via the <code>cyg_io_set_config()</code> and <code>cyg_io_get_config()</code> functions.</p>
+		<h4>Device configuration</h4>
+		<p><code>typedef struct cyg_can_info_st {<br>
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_can_baud_rate_t   baud;<br>
+				} cyg_can_info_t;</code></p>
+		<p>Device configuration is achieved by  by exchanging <code>cyg_can_info_t </code>data structures with the driver via the <code>cyg_io_set_config()</code> and <code>cyg_io_get_config()</code> functions using the config keys <code>CYG_IO_GET_CONFIG_CAN_INFO </code>and<code> CYG_IO_SET_CONFIG_CAN_INFO</code>. The field <i>baud</i> contains a baud rate selection. This must be one of the follwing values:</p>
+		<p><code>CYGNUM_CAN_KBAUD_10<br>
+				CYGNUM_CAN_KBAUD_20<br>
+				CYGNUM_CAN_KBAUD_50<br>
+				CYGNUM_CAN_KBAUD_100<br>
+				CYGNUM_CAN_KBAUD_125<br>
+				CYGNUM_CAN_KBAUD_250<br>
+				CYGNUM_CAN_KBAUD_500<br>
+				CYGNUM_CAN_KBAUD_800<br>
+				CYGNUM_CAN_KBAUD_1000<br>
+			</code></p>
+		<h4>Timeout configuration</h4>
+		<p><code>typedef struct cyg_can_timeout_info_st<br>
+				{<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_uint32 rx_timeout; <br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_uint32 tx_timeout;<br>
+				} cyg_can_timeout_info_t;<br>
+			</code></p>
+		<p>Timeout configuration is achieved by by exchanging <code>cyg_can_timeout_info_t </code>data structures with the driver via the <code>cyg_io_set_config()</code> and <code>cyg_io_get_config()</code> functions using the config keys <code>CYG_IO_SET_CONFIG_CAN_TIMEOUT </code>and<code> CYG_IO_SET_CONFIG_CAN_TIMEOUT</code>.  The field <i>rx_timeout</i> contains the timeout value for <code>cyg_io_read </code>calls and <i>tx_timeout</i> contains the timeout value for  <code>cyg_io_write </code>calls. This call is only available if the configuration options <code>CYGOPT_IO_CAN_SUPPORT_NONBLOCKING  </code>and <code>CYGOPT_IO_CAN_SUPPORT_TIMEOUTS</code> are enabled.</p>
+		<h4>Reading buffer configuration</h4>
+		<p><code>typedef struct cyg_can_buf_info_st<br>
+				{  <br>
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_int32 rx_bufsize; <br>
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_int32 rx_count;<br>
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_int32 tx_bufsize;<br>
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_int32 tx_count;<br>
+				} cyg_can_buf_info_t;<br>
+			</code></p>
+		<p><code>CYG_IO_GET_CONFIG_CAN_BUFFER_INFO - </code>This function retrieves the current state of the software buffers in the serial drivers. For the transmit buffer it returns the the total number of  <code>cyg_can_message </code>objects in buffer and the current number of  <code>cyg_can_message </code>objects occupied in the buffer. For the recieve buffer it returns the total number of  <code>cyg_can_event </code>objects in receive buffer and the current number of  <code>cyg_can_event </code>objects occupied  in the buffer. It does not take into account any buffering such as FIFOs or holding registers that the CAN hardware device itself may have.</p>
+		<h4>Configuring blocking/nonblocking calls</h4>
+		By default all calls to <code>cyg_io_read()</code> and<code> cyg_io_write()</code> are blocking calls. The config keys<br>
+		<br>
+		<code>CYG_IO_GET_CONFIG_READ_BLOCKING<br>
+			CYG_IO_GET_CONFIG_WRITE_BLOCKING<br>
+			<br>
+		</code>and<br>
+		<br>
+		<code>CYG_IO_GET_CONFIG_READ_BLOCKING<br>
+			CYG_IO_GET_CONFIG_WRITE_BLOCKING<br>
+			<br>
+		</code>enable switching between blocking and nonblocking calls separatly for read and write calls. If  blocking calls are configured then the read/write functions return only if a message was stored into TX buffer or a event was received from RX buffer. If nonblocking calls are enabled and there is no space in TX buffer or RX buffer is empty then the function returns immediatelly with <code>-EAGAIN</code>. If nonblocking calls are enabled and additionally timeouts are supported by driver, then the read/write functions wait until  timeout value is expired and then return witn <code>-EINTR</code>. If the read/write operation succeeds during the timed wait then the functions return succesfully with<code> ENOERR</code>.
+
+		<h4>Remote frame response buffer configuration</h4>
+		<p>The remote frame is a message frame which is transmitted to request a data frame. Some CAN hardware generates receive interrupts when a remote transmission request arrives. Other CAN hardware, i.e. the FlexCAN module, does not generate any receive interrupt. These CAN hardware chips, i.e. the FlexCAN module, can be configured to transmit a data frame automatically in response to a remote frame. In oder to support any kind of CAN hardware the eCos CAN driver provides a generic handling of remote transmission requests.</p>
+		<p>The transmission of the data frame in response of the remote frame is completely handled by the CAN driver. If the hardware driver, like the driver for the FlexCAN modul, supports harware message buffers, then the response frame is automatically transmitted if a remote transmission request with a matching ID arrives. If a CAN hardware does provide hardware support for sending the data frames in response to a remote frame, then this need to be implemented in software by the hardware device driver.</p>
+		<p>In order to respond to a remote frame, a remote frame reponse buffer need to be initialized before a data frame CAN be sent in response to a remote frame. This is achieved by by exchanging <code>cyg_can_rtr_buf_t </code>data structures with the driver via the <code>cyg_io_set_config()</code> function using the config key <code>CYG_IO_SET_CONFIG_CAN_RTR_BUF</code>. Once the buffer is initialized, the CAN data can be changed at any time by the application.</p>
+		<p><code>typedef struct cyg_can_rtr_buf_st<br>
+			</code><code>{<br>
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_int8        handle;<br>
+				&nbsp;&nbsp;&nbsp;&nbsp;cyg_can_message msg;<br>
+			</code><code>} cyg_can_rtr_buf_t;<br>
+			</code></p>
+		<p>The CAN frame that should be transmitted in response to a remote frame is stored in the<i> msg</i> field of the <code>cyg_can_rtr_buf_t </code>data structure. If there is no buffer initialized for this data, the value of the <i>handle</i> field need to be set to <code>CYGNUM_CAN_RTR_BUF_INIT</code>. After the call to  <code>cyg_io_set_config()</code> the <i>handle</i> field contains a valid value ( &gt;= 0) or the value <code>CYGNUM_CAN_RTR_BUF_NA</code>  ( &lt; 0) if no free buffer is available. With the valid handle value the CAN data can be changed later by calling  <code>cyg_io_set_config().</code></p>
+		<p>Example code for setting up a remote response buffer:</p>
+		<p><code>cyg_can_rtr_buf_t      rtr_buf;<br>
+				<br>
+				// prepare the remote response buffer<br>
+			</code><code>rtr_buf.handle &nbsp;= CYGNUM_CAN_RTR_BUF_INIT;<br>
+			</code><code>rtr_buf.msg.id&nbsp; = 0x7FF;<br>
+			</code><code>rtr_buf.msg.ext     = CYGNUM_CAN_ID_STD;<br>
+			</code><code>rtr_buf.msg.rtr     = CYGNUM_CAN_FRAME_DATA;<br>
+			</code><code>rtr_buf.msg.dlc     = 1;<br>
+			</code><code>rtr_buf.msg.data[0] = 0xAB;<br>
+				<br>
+				len = sizeof(rtr_buf);<br>
+			</code><code>if (ENOERR != cyg_io_set_config(hDrvFlexCAN, <br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CYG_IO_SET_CONFIG_CAN_RTR_BUF ,<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;rtr_buf, &amp;len))<br>
+			</code><code>{<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;// handle configuration error<br>
+			</code><code>} <br>
+			</code><code><br>
+			</code><code>if (rtr_buf.handle == CYGNUM_CAN_RTR_BUF_NA)<br>
+			</code><code>{<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;// no free message buffer available - handle this problem here<br>
+			</code><code>}<br>
+				<br>// change CAN data for a buffer that is already initialized<br>
+				rtr_buf.msg.data[0] = 0x11;<br>
+				<br>
+				len = sizeof(rtr_buf);<br>
+			</code><code>if (ENOERR != cyg_io_set_config(hDrvFlexCAN, <br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CYG_IO_SET_CONFIG_CAN_RTR_BUF ,<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;rtr_buf, &amp;len))<br>
+			</code><code>{<br>
+				
+				&nbsp;&nbsp;&nbsp;&nbsp;// handle configuration error<br>
+			</code><code>} <br>
+			</code></p>
+		<h2>FlexCAN device driver</h2>
+		<p>The FlexCAN module is a communication controller implementing the controller area network (CAN) protocol, an asynchronous communications protocol used in automotive and industrial control systems. It is a high speed (1 Mbit/sec), short distance, priority based protocol which can communicate using a variety of mediums (for example, fiber optic cable or an unshielded twisted pair of wires). The FlexCAN supports both the standard and extended identifier (ID) message formats specified in the CAN protocol specification, revision 2.0, part B.</p>
+		<p>It supports up to 16 flexible flexible message buffers of 0&#150;8 bytes data length, each configurable as Rx or Tx, all supporting standard and extended messages.</p>
+		<p>The FlexCAN device driver currently supports two message buffers for sending and receiving CAN messages - message buffer 14 for receiving CAN messages and message buffer 15 for transmitting CAN messages. The receive mask of message buffer 14 is configured in a way that it is possible to receive any kind of CAN message. Message buffers 0 - 13 can be used for setting up remote frame response buffers.</p>
+	</body>
+
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/packages/io/can/current/include/can.h
@@ -0,0 +1,199 @@
+#ifndef CYGONCE_CAN_H
+#define CYGONCE_CAN_H
+// ====================================================================
+//
+//      can.h
+//
+//      Device I/O 
+//
+// ====================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+// ====================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Uwe Kindler
+// Contributors: gthomas
+// Date:         2005-12-05
+// Purpose:      Internal interfaces for CAN I/O drivers
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+// ====================================================================
+
+
+//==========================================================================
+//                                INCLUDES
+//==========================================================================
+#include <pkgconf/system.h>
+#include <pkgconf/io_can.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/io/io.h>
+#include <cyg/io/canio.h>
+#include <cyg/io/devtab.h>
+#include <cyg/hal/drv_api.h>
+
+
+//===========================================================================
+//                            FORWARD DECLARATIONS
+//===========================================================================
+typedef struct can_channel       can_channel;
+typedef struct can_lowlevel_funs can_lowlevel_funs;
+
+
+//===========================================================================
+//                                DATA TYPES
+//===========================================================================
+
+//---------------------------------------------------------------------------
+// Pointers into uper-level driver which ISRs and DSRs need
+//
+typedef struct 
+{
+    void (*can_init)(can_channel *chan);              // Initialize the can channel
+    void (*xmt_msg)(can_channel *chan, void *pdata);  // transmit one single message
+    void (*rcv_event)(can_channel *chan, void *pdata);// indicate can event occurance
+} can_callbacks_t;
+
+
+#define CAN_CALLBACKS(_l,_init,_xmt_msg,_rcv_event)  \
+can_callbacks_t _l = {                               \
+    _init,                                           \
+    _xmt_msg,                                        \
+    _rcv_event                                       \
+};
+
+extern can_callbacks_t cyg_io_can_callbacks;
+
+
+//---------------------------------------------------------------------------
+// Data buffer for receive and transmit FIFOs
+//
+typedef struct can_cbuf_st
+{
+    void                    *pdata;      // points to data buffer
+    volatile int             put;
+    volatile int             get;
+    int                      len;
+    volatile int             data_cnt;   // count of events or messages currently in buffer
+    cyg_drv_cond_t           wait;
+    cyg_drv_mutex_t          lock;
+    bool                     waiting;
+#if defined(CYGOPT_IO_CAN_SUPPORT_NONBLOCKING)
+    bool                     blocking;   // true - timeouts will bes used, false - call blocks until data arrives
+#endif    
+    volatile bool            abort;      // Set by an outsider to kill processing
+    volatile cyg_int32       pending;    // This many bytes waiting to be sent
+#if defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS)
+    cyg_uint32               timeout;    // timeout value for reading data from buffer
+#endif
+} can_cbuf_t;
+
+
+#ifdef CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
+#define _TX_TIMEOUT CYGNUM_IO_CAN_DEFAULT_TIMEOUT_WRITE
+#define _RX_TIMEOUT CYGNUM_IO_CAN_DEFAULT_TIMEOUT_READ
+#define CBUF_INIT(_data, _len, _timeout)   \
+   {_data, 0, 0, _len, timeout : _timeout}
+#else
+#define _TX_TIMEOUT 0
+#define _RX_TIMEOUT 0
+#define CBUF_INIT(_data, _len, _timeout)   \
+   {_data, 0, 0, _len, }
+#endif // #ifdef CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
+ 
+   
+//---------------------------------------------------------------------------
+// Private data which describes this channel + initialisation macro
+//
+struct can_channel 
+{
+    can_lowlevel_funs  *funs;
+    can_callbacks_t    *callbacks;
+    void               *dev_priv;  // Whatever is needed by actual device routines
+    cyg_can_info_t      config;    // Current configuration
+    bool                init;      // true if driver is already initialized
+    can_cbuf_t          out_cbuf;  // buffer for transmit can messages
+    can_cbuf_t          in_cbuf;   // buffer with received can events
+};
+
+
+
+#define CAN_CHANNEL_USING_INTERRUPTS(_l,                                \
+                       _funs,                                           \
+                       _dev_priv,                                       \
+                       _baud,                                           \
+                       _out_buf, _out_buflen,                           \
+                       _in_buf, _in_buflen)                             \
+can_channel _l = {                                                      \
+    &_funs,                                                             \
+    &cyg_io_can_callbacks,                                              \
+    &(_dev_priv),                                                       \
+    CYG_CAN_INFO_INIT(_baud),                                           \
+    false,                                                              \
+    CBUF_INIT(_out_buf, _out_buflen, _TX_TIMEOUT),                      \
+    CBUF_INIT(_in_buf, _in_buflen, _RX_TIMEOUT)                         \
+};
+
+
+
+//---------------------------------------------------------------------------
+// Low level interface functions - these functions are required by the generic 
+// CAN driver in order to access the low level hardware
+//
+struct can_lowlevel_funs 
+{
+    bool (*putmsg)(can_channel *priv, cyg_can_message *pmsg, void *pdata);   // send one can message - return true if consumed
+    bool (*getevent)(can_channel *priv, cyg_can_event *pevent, void *pdata); // fetch one CAN event from device
+    Cyg_ErrNo (*set_config)(can_channel    *priv,                        // Change hardware configuration (baud rate, etc)
+                            cyg_uint32      key, 
+                            const void     *xbuf,
+                            cyg_uint32     *len);
+    void (*start_xmit)(can_channel *priv);                               // Enable the transmit channel and turn on transmit interrupts
+    void (*stop_xmit)(can_channel *priv);                                // Disable the transmit channel and turn transmit interrupts off
+};
+
+#define CAN_LOWLEVEL_FUNS(_l,_putmsg,_getevent,_set_config,_start_xmit,_stop_xmit)  \
+can_lowlevel_funs _l = {                                                            \
+  _putmsg,                                                                          \
+  _getevent,                                                                        \
+  _set_config,                                                                      \
+  _start_xmit,                                                                      \
+  _stop_xmit                                                                        \
+};
+
+extern cyg_devio_table_t cyg_io_can_devio;
+//-------------------------------------------------------------------------
+#endif // CYGONCE_SERIAL_H
new file mode 100644
--- /dev/null
+++ b/packages/io/can/current/include/canio.h
@@ -0,0 +1,215 @@
+#ifndef CYGONCE_CANIO_H
+#define CYGONCE_CANIO_H
+// ====================================================================
+//
+//      canio.h
+//
+//      Device I/O 
+//
+// ====================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+// ====================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Uwe Kindler
+// Contributors: gthomas
+// Date:         2005-05-12
+// Purpose:      Special support for CAN I/O devices
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+// ====================================================================
+
+
+//===========================================================================
+//                               INCLUDES
+//===========================================================================
+#include <pkgconf/system.h>
+#include <pkgconf/io_can.h>
+#include <pkgconf/hal.h>
+#include <cyg/infra/cyg_type.h>
+#include <cyg/io/config_keys.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+//===========================================================================
+//                                DATA TYPES
+//===========================================================================
+
+//
+// Supported baud rates
+//
+typedef enum {
+    CYGNUM_CAN_KBAUD_10 = 1,
+    CYGNUM_CAN_KBAUD_20,
+    CYGNUM_CAN_KBAUD_50,
+    CYGNUM_CAN_KBAUD_100,
+    CYGNUM_CAN_KBAUD_125,
+    CYGNUM_CAN_KBAUD_250,
+    CYGNUM_CAN_KBAUD_500,
+    CYGNUM_CAN_KBAUD_800,
+    CYGNUM_CAN_KBAUD_1000,
+} cyg_can_baud_rate_t;
+#define CYGNUM_CAN_KBAUD_MIN CYGNUM_CAN_KBAUD_10 
+#define CYGNUM_CAN_KBAUD_MAX CYGNUM_CAN_KBAUD_1000
+
+
+// Note: two levels of macro are required to get proper expansion.
+#define _CYG_CAN_BAUD_RATE(n) CYGNUM_CAN_KBAUD_##n
+#define CYG_CAN_BAUD_RATE(n) _CYG_CAN_BAUD_RATE(n)
+
+//
+// Event types for received events. Not all event types are supported by each CAN
+// hardware but normally these events should cover the most common CAN events
+// that may occur. A combination of the event type values is allowed.
+//
+typedef enum 
+{
+    CYGNUM_CAN_EVENT_RX                  = 0x0001, // message received
+    CYGNUM_CAN_EVENT_TX                  = 0x0002, // mesage transmitted
+    CYGNUM_CAN_EVENT_WARNING_RX          = 0x0004, // tx error counter (TEC) reached warning level (>96)
+    CYGNUM_CAN_EVENT_WARNING_TX          = 0x0008, // rx error counter (REC) reached warning level (>96)
+    CYGNUM_CAN_EVENT_ERR_PASSIVE         = 0x0010, // CAN "error passive" occured
+    CYGNUM_CAN_EVENT_BUS_OFF             = 0x0020, // CAN "bus off" error occured
+    CYGNUM_CAN_EVENT_OVERRUN_RX          = 0x0040, // overrun in RX queue or hardware occured
+    CYGNUM_CAN_EVENT_OVERRUN_TX          = 0x0080, // overrun in TX queue occured
+    CYGNUM_CAN_EVENT_CAN_ERR             = 0x0100, // a CAN bit or frame error occured
+    CYGNUM_CAN_EVENT_LEAVING_STANDBY     = 0x0200, // CAN hardware leaves standby / power don mode or is waked up
+    CYGNUM_CAN_EVENT_ENTERING_STANDBY    = 0x0400, // CAN hardware enters standby / power down mode
+    CYGNUM_CAN_EVENT_ARBITRATION_LOST    = 0x0800, // arbitration lost
+    CYGNUM_CAN_EVENT_DEVICE_CHANGED      = 0x1000, // device changed event
+} cyg_can_event_flags;
+
+//
+// Type of CAN identifier. 
+//
+typedef enum
+{
+    CYGNUM_CAN_ID_STD = 0x00, // standard ID 11 Bit
+    CYGNUM_CAN_ID_EXT = 0x01  // extended ID 29 Bit
+} cyg_can_id_type;
+
+//
+// Type of CAN frame
+//
+typedef enum
+{
+    CYGNUM_CAN_FRAME_DATA = 0x00, // CAN data frame
+    CYGNUM_CAN_FRAME_RTR  = 0x01  // CAN remote transmission request
+} cyg_can_frame_type;
+
+
+//
+// CAN message type for transport or transmit of CAN messages 
+//
+typedef struct can_message
+{
+    cyg_uint32          id;     // 11 Bit or 29 Bit CAN identifier - cyg_can_id_type 
+    cyg_uint8           data[8];// 8 data bytes
+    cyg_can_id_type     ext;    // CYGNUM_CAN_ID_STD = 11 Bit CAN id, CYGNUM_CAN_ID_EXT = 29 Bit CAN id
+    cyg_can_frame_type  rtr;    // CYGNUM_CAN_FRAME_DATA = data frame, CYGNUM_CAN_FRAME_RTR = remote transmission request
+    cyg_uint8           dlc;    // data length code (number of bytes (0 - 8) containing valid data
+} cyg_can_message;
+
+//
+// CAN event type for reception of CAN events from driver. CAN events may be
+// a received CAN message or any other status information like tx msg or
+// arbitration lost
+//
+typedef struct cyg_can_event_st
+{
+    cyg_uint32      timestamp;
+    cyg_can_message msg;
+    cyg_uint16      flags;     
+} cyg_can_event;
+
+//
+// CAN configuration - at the moment there is only one data member but we are
+// prepared for future enhancements
+//
+typedef struct cyg_can_info_st {
+    cyg_can_baud_rate_t   baud;
+} cyg_can_info_t;
+
+//
+// buffer configuration - bufsize and count for tx are the number of messages
+// and for rx the number of events
+//
+typedef struct cyg_can_buf_info_st
+{  
+    cyg_int32 rx_bufsize; 
+    cyg_int32 rx_count;
+    cyg_int32 tx_bufsize;
+    cyg_int32 tx_count;
+} cyg_can_buf_info_t;
+
+//
+// Timeout configuration
+//
+typedef struct cyg_can_timeout_info_st
+{
+    cyg_uint32 rx_timeout; 
+    cyg_uint32 tx_timeout;
+} cyg_can_timeout_info_t;
+
+//
+// this data type defines a remote transmission request buffer
+//
+typedef struct cyg_can_rtr_buf_st
+{
+    cyg_int8        handle;
+    cyg_can_message msg;
+} cyg_can_rtr_buf_t;
+
+//
+// Values for the handle field of the cyg_can_rtr_buf_t data structure
+//
+#define CYGNUM_CAN_RTR_BUF_NA    -0x01 // no free message buffer available
+#define CYGNUM_CAN_RTR_BUF_INIT  -0x02 // initialize the remote message buffer
+
+
+#define CYG_CAN_INFO_INIT(_baud) \
+  { _baud}
+
+#ifdef __cplusplus
+}
+#endif
+
+//---------------------------------------------------------------------------
+#endif // CYGONCE_CANIO_H
new file mode 100644
--- /dev/null
+++ b/packages/io/can/current/src/can.c
@@ -0,0 +1,645 @@
+//==========================================================================
+//
+//      io/can/common/can.c
+//
+//      High level CAN driver
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2003 Gary Thomas
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Uwe Kindler
+// Contributors: Uwe Kindler
+// Date:         2005-05-12
+// Purpose:      Top level CAN driver
+// Description: 
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+
+//==========================================================================
+//                              INCLUDES
+//==========================================================================
+#include <pkgconf/io.h>
+#include <pkgconf/io_can.h>
+
+#include <cyg/io/io.h>
+#include <cyg/io/devtab.h>
+#include <cyg/io/can.h>
+#include <cyg/infra/cyg_ass.h>      // assertion support
+#include <cyg/infra/diag.h>         // diagnostic output
+
+
+//==========================================================================
+//                                MACROS
+//==========================================================================
+#ifdef CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
+#define CYG_DRV_COND_WAIT(_cond, _time) cyg_cond_timed_wait(_cond, cyg_current_time() + (_time))
+#else
+#define CYG_DRV_COND_WAIT(_cond, _time) cyg_drv_cond_wait(_cond)
+#endif
+
+
+//==========================================================================
+//                            LOCAL FUNCTIONS
+//==========================================================================
+//
+// Device I/O functions
+//
+static Cyg_ErrNo can_write(cyg_io_handle_t handle, const void *_buf, cyg_uint32 *len);
+static Cyg_ErrNo can_read(cyg_io_handle_t handle, void *_buf, cyg_uint32 *len);
+static cyg_bool  can_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info);
+static Cyg_ErrNo can_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *xbuf, cyg_uint32 *len);
+static Cyg_ErrNo can_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *xbuf, cyg_uint32 *len);
+
+//
+// Callback functions into upper layer driver
+//
+static void can_init(can_channel *chan);    
+static void can_rcv_event(can_channel *chan, void *pdata);
+static void can_xmt_msg(can_channel *chan, void *pdata);
+
+//
+// Device I/O table
+//
+DEVIO_TABLE(cyg_io_can_devio,
+            can_write,
+            can_read,
+            can_select,
+            can_get_config,
+            can_set_config
+    );
+
+
+//
+// Callbacks into upper layer driver
+//
+CAN_CALLBACKS(cyg_io_can_callbacks, 
+              can_init, 
+              can_xmt_msg,
+              can_rcv_event);
+
+
+//===========================================================================
+// Initialize CAN driver
+//===========================================================================
+static void can_init(can_channel *chan)
+{
+    can_cbuf_t *cbuf;
+    
+    if (chan->init) 
+    {
+        return;
+    }
+    
+    cbuf = &chan->in_cbuf;
+    cbuf->waiting  = false;
+    cbuf->abort    = false;
+#ifdef CYGOPT_IO_CAN_SUPPORT_NONBLOCKING
+    cbuf->blocking = true;
+#endif
+    cyg_drv_mutex_init(&cbuf->lock);
+    cyg_drv_cond_init(&cbuf->wait, &cbuf->lock);
+    
+    cbuf = &chan->out_cbuf;
+    cbuf->waiting  = false;
+    cbuf->abort    = false;
+#ifdef CYGOPT_IO_CAN_SUPPORT_NONBLOCKING
+    cbuf->blocking = true;
+#endif
+    cyg_drv_mutex_init(&cbuf->lock);
+    cyg_drv_cond_init(&cbuf->wait, &cbuf->lock);
+    
+    chan->init = true;
+}
+
+
+//===========================================================================
+// Write exactly one CAN message to CAN bus
+//===========================================================================
+static Cyg_ErrNo can_write(cyg_io_handle_t handle, const void *_buf, cyg_uint32 *len)
+{
+    cyg_devtab_entry_t *t      = (cyg_devtab_entry_t *)handle;
+    can_channel        *chan   = (can_channel *)t->priv;
+    can_lowlevel_funs  *funs   = chan->funs;
+    Cyg_ErrNo           res    = ENOERR;
+    can_cbuf_t         *cbuf   = &chan->out_cbuf;
+    cyg_uint32          size   = *len;
+    
+    //
+    // the user need to provide a can message buffer
+    //
+    if (*len != sizeof(cyg_can_message))
+    {
+        return -EINVAL;
+    }
+    
+    cyg_drv_mutex_lock(&cbuf->lock);
+    cbuf->abort = false;
+    cyg_drv_dsr_lock(); // avoid race condition while testing pointers
+    
+    while (size > 0)
+    {
+        if (cbuf->data_cnt == cbuf->len) 
+        {
+            cbuf->waiting = true;      // Buffer full - wait for space
+            funs->start_xmit(chan);    // Make sure xmit is running
+            //
+            // Check flag: 'start_xmit' may have obviated the need
+            // to wait
+            //
+            if (cbuf->waiting) 
+            {
+                cbuf->pending += size;  // Have this much more to send [eventually]
+#if defined(CYGOPT_IO_CAN_SUPPORT_NONBLOCKING)
+#if defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS)
+                //
+                // If timeouts are enabled and we use nonblocking calls then we
+                // can use the timeout values
+                //
+                if (!cbuf->blocking)
+                {
+                    if(!CYG_DRV_COND_WAIT(&cbuf->wait, cbuf->timeout))
+                    {
+                        cbuf->abort = true;
+                    }
+                } // if (!cbuf->blocking)#
+                else
+#else // #if defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS)
+                //
+                // if this is a nonblocking call then we return immediatelly
+                //
+                if (!cbuf->blocking)
+                {
+                    *len = 0;
+                    res = -EAGAIN;
+                    break;
+                }
+                else
+#endif // #if defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS)
+#endif //defined(CYGOPT_IO_CAN_SUPPORT_NONBLOCKING)
+                {
+                    if(!cyg_drv_cond_wait(&cbuf->wait))
+                    {
+                        cbuf->abort = true;
+                    }
+                }
+                cbuf->pending -= size;
+                if (cbuf->abort) 
+                {
+                    // Give up!
+                    *len -= size;   // number of characters actually sent
+                     cbuf->abort = false;
+                     cbuf->waiting = false;
+                     res = -EINTR;
+                     break;
+                } // if (cbuf->abort) 
+            } // if (cbuf->waiting)
+        } // if (cbuf->data_cnt == cbuf->len) 
+        else
+        {           
+            //
+            // there is enougth space left so we can store additional data
+            //
+            cyg_can_message *ptxbuf       = (cyg_can_message *)cbuf->pdata;
+            cyg_can_message *pbuf_message = &ptxbuf[cbuf->put];
+            cyg_can_message *pmessage     = (cyg_can_message *)_buf;
+            
+            *pbuf_message = *pmessage; // copy message
+   
+            cbuf->put = (cbuf->put + 1) % cbuf->len;
+            cbuf->data_cnt++;   
+            size -= sizeof(cyg_can_message);   
+        }
+    } // while (size > 0)
+    
+    (funs->start_xmit)(chan);  // Start output as necessary
+    cyg_drv_dsr_unlock();            
+    cyg_drv_mutex_unlock(&cbuf->lock);
+    return res;
+}
+
+
+//===========================================================================
+// Read one single CAN event from hw
+//===========================================================================
+static Cyg_ErrNo can_read(cyg_io_handle_t handle, void *_buf, cyg_uint32 *len)
+{
+    cyg_devtab_entry_t *t      = (cyg_devtab_entry_t *)handle;
+    can_channel        *chan   = (can_channel *)t->priv;
+    can_cbuf_t         *cbuf   = &chan->in_cbuf;
+    cyg_uint32          size   = 0;
+    Cyg_ErrNo           res    = ENOERR;
+    
+    //
+    // the user need to provide a can event buffer
+    //
+    if (*len != sizeof(cyg_can_event))
+    {
+        return -EINVAL;
+    }
+    
+    cyg_drv_mutex_lock(&cbuf->lock);
+    cbuf->abort = false;
+    
+    cyg_drv_dsr_lock();  // avoid race conditions
+    while (size < *len)
+    {
+        //
+        // if message buffer contains at least one message then read the
+        // oldest message from buffer and return
+        //
+        if (cbuf->data_cnt > 0)
+        {
+            cyg_can_event *prxbuf     = (cyg_can_event *)cbuf->pdata;   
+            cyg_can_event *pbuf_event = &prxbuf[cbuf->get];
+            cyg_can_event *pevent     = (cyg_can_event *)_buf;
+
+            *pevent = *pbuf_event; // copy event
+            
+            cbuf->get = (cbuf->get + 1) % cbuf->len;
+            cbuf->data_cnt--; 
+            size += sizeof(cyg_can_event);
+        }
+        else
+        {
+            //
+            // if messaeg buffer does not contain any message, then wait until
+            // a message arrives or return immediatelly if nonblocking calls are
+            // supported
+            //
+            cbuf->waiting = true;
+#if defined(CYGOPT_IO_CAN_SUPPORT_NONBLOCKING)
+#if defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS)
+            //
+            // If timeouts are enabled and we use nonblocking calls then we
+            // can use the timeout values
+            //
+            if (!cbuf->blocking)
+            {
+                if(!CYG_DRV_COND_WAIT(&cbuf->wait, cbuf->timeout))
+                {
+                    cbuf->abort = true;
+                }
+            } // if (!cbuf->blocking)#
+            else
+#else // #if defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS)
+            //
+            // if this is a nonblocking call then we return immediatelly
+            //
+            if (!cbuf->blocking)
+            {
+                *len = 0;
+                res = -EAGAIN;
+                break;
+            }
+            else
+#endif // #if defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS)
+#endif // #if defined(CYGOPT_IO_CAN_SUPPORT_NONBLOCKING)
+            {
+                if(!cyg_drv_cond_wait(&cbuf->wait))
+                {
+                    cbuf->abort = true;
+                }
+            }
+            
+            if (cbuf->abort)
+            {
+                *len = size;
+                cbuf->abort = false;
+                cbuf->waiting = false;
+                res = -EINTR;
+                break;
+            }
+        }
+    } // while (size < *len)
+    cyg_drv_dsr_unlock();
+    
+    cyg_drv_mutex_unlock(&cbuf->lock);
+    
+    return res;
+}
+
+
+//===========================================================================
+// Query CAN channel configuration data
+//===========================================================================
+static Cyg_ErrNo can_get_config(cyg_io_handle_t handle, 
+               cyg_uint32      key, 
+               void           *xbuf,
+               cyg_uint32     *len)
+{
+    cyg_devtab_entry_t *t         = (cyg_devtab_entry_t *)handle;
+    can_channel        *chan      = (can_channel *)t->priv;
+    Cyg_ErrNo           res       = ENOERR;
+    cyg_can_info_t     *pcan_info = (cyg_can_info_t *)xbuf;
+    can_cbuf_t         *out_cbuf  = &chan->out_cbuf;
+    can_cbuf_t         *in_cbuf   = &chan->in_cbuf;
+    
+    switch (key)
+    {
+        case CYG_IO_GET_CONFIG_CAN_INFO :
+             if (*len < sizeof(cyg_can_info_t)) 
+             {
+                 return -EINVAL;
+             }
+             *pcan_info = chan->config;
+             *len       = sizeof(chan->config);
+             break;
+        //
+        // return rx/tx buffer sizes and counts 
+        //    
+        case CYG_IO_GET_CONFIG_CAN_BUFFER_INFO :
+             {
+                 cyg_can_buf_info_t *pbuf_info;
+                 if (*len < sizeof(cyg_can_buf_info_t))
+                 {
+                     return -EINVAL; 
+                 } 
+          
+                *len = sizeof(cyg_can_buf_info_t);
+                pbuf_info = (cyg_can_buf_info_t *)xbuf;
+                pbuf_info->rx_bufsize = in_cbuf->len;
+                if (pbuf_info->rx_bufsize)
+                {
+                    pbuf_info->rx_count = in_cbuf->data_cnt ;
+                }
+                else
+                {
+                    pbuf_info->rx_count = 0;
+                }            
+                pbuf_info->tx_bufsize = out_cbuf->len;
+                if (pbuf_info->tx_bufsize)
+                {
+                    pbuf_info->tx_count = out_cbuf->data_cnt;
+                }
+                else
+                {
+                    pbuf_info->tx_count = 0;
+                }
+            }
+            break; // case CYG_IO_GET_CONFIG_CAN_BUFFER_INFO
+
+#ifdef CYGOPT_IO_CAN_SUPPORT_TIMEOUTS            
+            //
+            // return current timeouts
+            //
+            case CYG_IO_GET_CONFIG_CAN_TIMEOUT :
+                 {
+                     cyg_can_timeout_info_t *ptimeout_info;
+                     if (*len < sizeof(cyg_can_timeout_info_t))
+                     {
+                         return -EINVAL; 
+                     } 
+                     
+                     *len = sizeof(cyg_can_timeout_info_t);
+                      ptimeout_info = (cyg_can_timeout_info_t *)xbuf;
+                      
+                      ptimeout_info->rx_timeout = in_cbuf->timeout;
+                      ptimeout_info->tx_timeout = out_cbuf->timeout;
+                 }
+                 break; // case CYG_IO_GET_CONFIG_CAN_TIMEOUT_INFO
+#endif // CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
+
+#ifdef CYGOPT_IO_CAN_SUPPORT_NONBLOCKING
+            case CYG_IO_GET_CONFIG_READ_BLOCKING:
+                 {
+                     if (*len < sizeof(cyg_uint32)) 
+                     {
+                         return -EINVAL;
+                     }
+                     *(cyg_uint32*)xbuf = (in_cbuf->blocking) ? 1 : 0;
+                 }
+                 break;
+
+            case CYG_IO_GET_CONFIG_WRITE_BLOCKING:
+                 {
+                     if (*len < sizeof(cyg_uint32))
+                     {
+                         return -EINVAL;
+                     }
+                     *(cyg_uint32*)xbuf = (out_cbuf->blocking) ? 1 : 0;
+                 }
+                 break;
+#endif // CYGOPT_IO_CAN_SUPPORT_NONBLOCKING
+        
+        default:
+            res = -EINVAL;   
+    } // switch (key)
+    
+    return res;
+}
+
+
+//===========================================================================
+// Set CAN channel configuration
+//===========================================================================
+static Cyg_ErrNo can_set_config(cyg_io_handle_t handle, 
+               cyg_uint32      key,
+               const void     *xbuf, 
+               cyg_uint32     *len)
+{
+    cyg_devtab_entry_t *t         = (cyg_devtab_entry_t *)handle;
+    can_channel        *chan      = (can_channel *)t->priv;
+    Cyg_ErrNo           res       = ENOERR;
+    can_lowlevel_funs  *funs      = chan->funs;
+    can_cbuf_t         *out_cbuf  = &chan->out_cbuf;
+    can_cbuf_t         *in_cbuf   = &chan->in_cbuf;
+    
+    switch (key)
+    {
+#ifdef CYGOPT_IO_CAN_SUPPORT_NONBLOCKING
+        case CYG_IO_SET_CONFIG_READ_BLOCKING:
+             {
+                 if (*len < sizeof(cyg_uint32) || 0 == in_cbuf->len) 
+                 {
+                     return -EINVAL;
+                 }
+                 in_cbuf->blocking = (1 == *(cyg_uint32*)xbuf) ? true : false;
+             }
+             break;
+             
+        case CYG_IO_SET_CONFIG_WRITE_BLOCKING:
+             {
+                 if (*len < sizeof(cyg_uint32) || 0 == out_cbuf->len) 
+                 {
+                     return -EINVAL;
+                 }
+                 out_cbuf->blocking = (1 == *(cyg_uint32*)xbuf) ? true : false;
+             }
+             break;
+#endif // CYGOPT_IO_CAN_SUPPORT_NONBLOCKING
+
+#ifdef CYGOPT_IO_CAN_SUPPORT_TIMEOUTS            
+        //
+        // return current timeouts
+        //
+        case CYG_IO_SET_CONFIG_CAN_TIMEOUT :
+             {
+                 cyg_can_timeout_info_t *ptimeout_info;
+                 if (*len < sizeof(cyg_can_timeout_info_t))
+                 {
+                     return -EINVAL; 
+                 } 
+                   
+                 *len = sizeof(cyg_can_timeout_info_t);
+                  ptimeout_info = (cyg_can_timeout_info_t *)xbuf;
+                   
+                  in_cbuf->timeout = ptimeout_info->rx_timeout;
+                  out_cbuf->timeout = ptimeout_info->tx_timeout;
+             }
+             break; // case CYG_IO_GET_CONFIG_CAN_TIMEOUT_INFO
+#endif // CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
+        
+        default:
+            //
+            // pass down to lower layers
+            //
+            res = (funs->set_config)(chan, key, xbuf, len);
+    } // switch (key)
+    
+    return res;
+}
+
+
+//===========================================================================
+// Select support for CAN channel
+//===========================================================================
+static cyg_bool can_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info)
+{
+    //
+    // do nothing here because we currently do not support select
+    //
+    return true;
+}
+
+
+//===========================================================================
+// Callback for received events
+//===========================================================================
+static void can_rcv_event(can_channel *chan, void *pdata)
+{
+    can_cbuf_t     *cbuf   = &chan->in_cbuf;
+    cyg_can_event  *prxbuf = (cyg_can_event *)cbuf->pdata;
+    
+    //
+    // cbuf is a ring buffer - if the buffer is full, then we overwrite the
+    // oldest message in buffer so the user will always get the actual and
+    // last state of the external hardware that is connected to the
+    // CAN bus. 
+    //
+    if (chan->funs->getevent(chan, &prxbuf[cbuf->put], pdata))
+    {
+        if (cbuf->data_cnt < cbuf->len)
+        {
+            cbuf->data_cnt++;
+        }
+        else
+        {
+            //
+            // the buffer is full but a new message arrived. We store this new
+            // message and overwrite the oldest one, but at least we tell the user
+            // that there is an overrun in RX queue
+            //
+            prxbuf[cbuf->put].flags |= CYGNUM_CAN_EVENT_OVERRUN_RX;
+            cbuf->get = (cbuf->get + 1) % cbuf->len;
+        }
+        
+        cbuf->put = (cbuf->put + 1) % cbuf->len;
+        
+        if (cbuf->waiting) 
+        {
+            cbuf->waiting = false;
+            cyg_drv_cond_broadcast(&cbuf->wait);
+        }
+    }
+}
+
+
+//===========================================================================
+// Callback function for transmit events
+//===========================================================================
+static void can_xmt_msg(can_channel *chan, void *pdata)
+{
+    can_cbuf_t        *cbuf    = &chan->out_cbuf;
+    can_lowlevel_funs *funs    = chan->funs;  
+    cyg_can_message   *ptxbuf  = (cyg_can_message *)cbuf->pdata;
+    cyg_can_message   *pbuf_txmsg;
+
+    //
+    // transmit messages as long as there are messages in the buffer 
+    //
+    while (cbuf->data_cnt > 0)
+    {
+        pbuf_txmsg = &ptxbuf[cbuf->get];
+        
+        if (funs->putmsg(chan, pbuf_txmsg, pdata))
+        {
+            cbuf->get = (cbuf->get + 1) % cbuf->len;
+            cbuf->data_cnt--;
+        }
+        else
+        {
+            //
+            // we are here because the hardware is busy at the moment and
+            // we can't send another message - now we check if there is already
+            // some space in buffer so we can wakeup the writer
+            //
+            if ((cbuf->len - cbuf->data_cnt) > 0)
+            {
+                if (cbuf->waiting)
+                {
+                    cbuf->waiting = false;
+                    cyg_drv_cond_broadcast(&cbuf->wait);
+                }
+            }
+            return;
+        }
+    } // while (cbuf->data_cnt > 0)
+    funs->stop_xmit(chan);  // Done with transmit
+    
+    if (cbuf->waiting)
+    {
+        cbuf->waiting = false;
+        cyg_drv_cond_broadcast(&cbuf->wait);
+    }            
+}
+
+
+//---------------------------------------------------------------------------
+// end of can.c
--- a/packages/io/common/current/include/config_keys.h
+++ b/packages/io/common/current/include/config_keys.h
@@ -128,6 +128,17 @@
 
 #define CYG_IO_GET_CONFIG_DISK_INFO              0x700
 
+// ======== 0x800 CAN ========================================================
+// Get/Set configuration 'key' values for DISK I/O 
+
+#define CYG_IO_GET_CONFIG_CAN_INFO                  0x0801
+#define CYG_IO_GET_CONFIG_CAN_BUFFER_INFO           0x0802
+#define CYG_IO_GET_CONFIG_CAN_TIMEOUT               0x0803
+
+#define CYG_IO_SET_CONFIG_CAN_INFO                  0x0881
+#define CYG_IO_SET_CONFIG_CAN_TIMEOUT               0x0883
+#define CYG_IO_SET_CONFIG_CAN_RTR_BUF               0x0884
+
 // ======== 0x1000 Generic ===================================================
 // Get/Set configuration 'key' values that can apply to more than one
 // class of device.