diff packages/devs/can/loop/current/src/loop_can.c @ 2830:3caad2060bd3

Strip erroneous CR chars from text files in the eCos repository. [ Bugzilla 1000694]
author jld
date Wed, 25 Feb 2009 12:50:14 +0000
parents 74dbf4c3f2e1
children
line wrap: on
line diff
--- a/packages/devs/can/loop/current/src/loop_can.c
+++ b/packages/devs/can/loop/current/src/loop_can.c
@@ -1,10 +1,10 @@
-//==========================================================================
-//
-//      loop_can.c
-//
-//      Loopback CAN device driver
-//
-//==========================================================================
+//==========================================================================
+//
+//      loop_can.c
+//
+//      Loopback CAN device driver
+//
+//==========================================================================
 // ####ECOSGPLCOPYRIGHTBEGIN####                                            
 // -------------------------------------------                              
 // This file is part of eCos, the Embedded Configurable Operating System.   
@@ -36,373 +36,373 @@
 // on this file might be covered by the GNU General Public 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/devs_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_DEVS_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 Cyg_ErrNo loop_can_get_config(can_channel *chan, cyg_uint32 key, 
-                                     const void*  buf,  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 33
-
-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_get_config,
-                  loop_can_set_config,
-                  loop_can_start_xmit,
-                  loop_can_stop_xmit
-     );
-
-//-------------------------------------------------------------------------
-// Hardware info for each serial line
-
-#ifdef CYGPKG_DEVS_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_DEVS_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_DEVS_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_DEVS_CAN_LOOP_CAN1
-    
-#ifdef CYGPKG_DEVS_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_DEVS_CAN_LOOP_CAN1
- 
- 
-  
-//-------------------------------------------------------------------------
-// And finally, the device table entries:
-//
-#ifdef CYGPKG_DEVS_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_DEVS_CAN_LOOP_CAN0
-
-#ifdef CYGPKG_DEVS_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_DEVS_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;
-#ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT 
-    struct fifo *frd = loop_chan->read_fifo;
-#endif
-
-    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;
-}
-
-//-------------------------------------------------------------------------
-// Query device configuration
-
-static Cyg_ErrNo 
-loop_can_get_config(can_channel *chan, cyg_uint32 key, 
-                    const void*  buf,  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
+//==========================================================================
+//#####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/devs_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_DEVS_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 Cyg_ErrNo loop_can_get_config(can_channel *chan, cyg_uint32 key, 
+                                     const void*  buf,  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 33
+
+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_get_config,
+                  loop_can_set_config,
+                  loop_can_start_xmit,
+                  loop_can_stop_xmit
+     );
+
+//-------------------------------------------------------------------------
+// Hardware info for each serial line
+
+#ifdef CYGPKG_DEVS_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_DEVS_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_DEVS_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_DEVS_CAN_LOOP_CAN1
+    
+#ifdef CYGPKG_DEVS_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_DEVS_CAN_LOOP_CAN1
+ 
+ 
+  
+//-------------------------------------------------------------------------
+// And finally, the device table entries:
+//
+#ifdef CYGPKG_DEVS_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_DEVS_CAN_LOOP_CAN0
+
+#ifdef CYGPKG_DEVS_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_DEVS_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;
+#ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT 
+    struct fifo *frd = loop_chan->read_fifo;
+#endif
+
+    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;
+}
+
+//-------------------------------------------------------------------------
+// Query device configuration
+
+static Cyg_ErrNo 
+loop_can_get_config(can_channel *chan, cyg_uint32 key, 
+                    const void*  buf,  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