]> git.kernelconcepts.de Git - karo-tx-redboot.git/blobdiff - packages/devs/can/m68k/mcf52xx/v2_0/src/can_mcf52xx.c
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / devs / can / m68k / mcf52xx / v2_0 / src / can_mcf52xx.c
index aea9c21ec2daa63ce8cc5ed42e4b378f4b334421..14323da89161554cc775d40da4853650f4c2b5ee 100644 (file)
 //
 #define FLEXCAN_ERR_EVENT                       16
 #define FLEXCAN_BUSOFF_EVENT                    17
+#define FLEXCAN_WAKE_EVENT                      18
+
+//
+// Acceptance mask
+//
+#define FLEXCAN_ACCEPTANCE_MASK_RX_ALL          0x00       // receive all messages - mbox ID does not matter
+#define FLEXCAN_ACCEPTANCE_MASK_RX_ID           0x1FFFFFFF // receive only messages where ID exactly matches mbox ID
 
 
 //---------------------------------------------------------------------------
 #define MBOX_CFG_STAT_MASK     0xF0
 
 
+//---------------------------------------------------------------------------
+// flexcan message buffer configuration
+//
+#define FLEXCAN_MBOX_MIN      0
+#define FLEXCAN_MBOX_MAX       15
+#define FLEXCAN_MBOX_CNT      16
+#define FLEXCAN_MBOX_TX       CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_TX_MBOX
+#define FLEXCAN_MBOX_RX_MIN   0
+#define FLEXCAN_MBOX_RX_MAX   (FLEXCAN_MBOX_MAX - 1) // one msg box is tx
+#define FLEXCAN_MBOX_RX_CNT   (FLEXCAN_MBOX_CNT - 1) // one msg box is tx
+
+
+#define FLEXCAN_CTRLSTAT_NOT_READ 0 // indicates that control status register is not read
+
+
 //===========================================================================
 //                                 DATA TYPES
 //===========================================================================
+//
+// Type of message buffer - required for function getevent in order to
+// identify the type of message box that cause event
+//
+typedef enum
+{
+    MBOX_STATE_DISABLED,  // message box unused (free)
+    MBOX_STATE_TX,        // TX message box
+    MBOX_STATE_REMOTE_TX, // remote TX msaage box (data will be sent on reception of rtr frame) 
+    MBOX_STATE_RX_ALL_STD, // RX message box for standard IDs
+    MBOX_STATE_RX_ALL_EXT, // RX message box for standard IDs
+    MBOX_STATE_RX_FILT     // RX message box for filter mboxes
+} flexcan_mbox_state;
+
+
 //
 // 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;  
+    cyg_vector_t       isr_vec;           // isr vector
+    int                isr_priority;      // isr priority
+    cyg_interrupt      interrupt;         // stores interrupt data
+    cyg_handle_t       interrupt_handle;  // stores interrupt number 
+    cyg_uint8          num;               // number of message buffer
+    bool               busy;              // if true, then transmission or reception is in progress
+    flexcan_mbox_state state;             // message box state
+    cyg_uint8          ctrlstat_shadow;   // shadow register of message box ctrlstat register
 } flexcan_mbox_info; 
 
 //
-// flexcan interrupt (busoff, err, wake) data
+// Between ISR and DSR handling there is some kind of circular buffer.
+// A DSR is only invoked if no other message box invoked a DSR before
+// the DSR will read all available message buffers. This structure
+// is for exchange of information between ISR and DSR
+//
+typedef struct st_rxmbox_circbuf
+{
+    cyg_uint8 idx_rd;       // the message box the DSR will read from
+    cyg_uint8 idx_wr;       // the message box that will receive the next message
+    cyg_uint8 count;        // the number of received message before DSR starts (number of ISR nesting)
+} flexcan_rxmbox_circbuf;
+
+//
+// flexcan interrupt (busoff, err, wake) data - stores interrupt data for
+// a non message box interrupt (bus off, err or wake interrupt)
 //
 typedef struct flexcan_int_st
 {
@@ -223,7 +277,8 @@ typedef struct flexcan_int_st
 #define FLEXCAN_MBOX_INIT(_mbox0_vec, _prio, _mbox_no) { \
     isr_vec      : (_mbox0_vec) + (_mbox_no),            \
     isr_priority : (_prio),                              \
-    num          : (_mbox_no)                            \
+    num          : (_mbox_no),                           \
+    busy         : false                                 \
 }
 
 //
@@ -240,23 +295,32 @@ typedef struct flexcan_int_st
 //
 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
+    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   mboxes[FLEXCAN_MBOX_CNT];// message boxes
+    cyg_uint32          last_tx_id;      // last transmitted message identifier
+    
+    flexcan_int         boff_int;        // bus off interrupt data
+    flexcan_int         err_int;         // error interrupt data
+    flexcan_int         wake_int;        // wake interrupt data
+    
+    cyg_uint8           tx_all_mbox;     // number of message box for all transmit messages
+    cyg_uint8           free_mboxes;     // number of free message boxes for msg filters and rtr buffers
+    cyg_can_state       state;           // state of CAN controller
+    
+    flexcan_rxmbox_circbuf rxmbox_std_circbuf;
+    flexcan_rxmbox_circbuf rxmbox_ext_circbuf;
+
+    cyg_uint8           mboxes_std_cnt;   // contains number of standard message boxes available
+    cyg_uint8           mboxes_ext_cnt;   // number of message boxes with ext id
+    cyg_uint8           mboxes_rx_all_cnt;// number of all available mboxes
+
+    bool                rx_all;           // true if reception of call can messages is active
+    cyg_uint16          imask_shadow;    // interrupt mask shadow register
+#ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT 
+    cyg_can_message     last_tx_msg;     // stores last transmitted message for TX events
+#endif
+
 #ifdef FLEXCAN_CAN_STATS
     cyg_uint32          isr_count;
     cyg_uint32          dsr_count;
@@ -273,22 +337,59 @@ typedef struct flexcan_info
 #define FLEXCAN_INFO(_l,                                                \
                      _baseaddr,                                         \
                      _isr_vec_mbox0,                                    \
-                     _rx_mbox_no, _rx_isr_prio,                         \
-                     _tx_mbox_no, _tx_isr_prio,                         \
+                     _mbox0_isr_prio,                                   \
+                     _mbox1_isr_prio,                                   \
+                     _mbox2_isr_prio,                                   \
+                     _mbox3_isr_prio,                                   \
+                     _mbox4_isr_prio,                                   \
+                     _mbox5_isr_prio,                                   \
+                     _mbox6_isr_prio,                                   \
+                     _mbox7_isr_prio,                                   \
+                     _mbox8_isr_prio,                                   \
+                     _mbox9_isr_prio,                                   \
+                     _mbox10_isr_prio,                                  \
+                     _mbox11_isr_prio,                                  \
+                     _mbox12_isr_prio,                                  \
+                     _mbox13_isr_prio,                                  \
+                     _mbox14_isr_prio,                                  \
+                     _mbox15_isr_prio,                                  \
                      _boff_isr_vec, _boff_isr_prio,                     \
-                     _err_isr_vec, _err_isr_prio)                       \
+                     _err_isr_vec, _err_isr_prio,                       \
+                     _wake_isr_vec, _wake_isr_prio,                     \
+                     _tx_all_mbox,                                      \
+                     _std_mboxes, _ext_mboxes)                          \
 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)       \
+    mboxes : {                                                          \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox0_isr_prio), 0),          \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox1_isr_prio), 1),          \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox2_isr_prio), 2),          \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox3_isr_prio), 3),          \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox4_isr_prio), 4),          \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox5_isr_prio), 5),          \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox6_isr_prio), 6),          \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox7_isr_prio), 7),          \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox8_isr_prio), 8),          \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox9_isr_prio), 9),          \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox10_isr_prio),10),         \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox11_isr_prio),11),         \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox12_isr_prio),12),         \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox13_isr_prio),13),         \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox14_isr_prio),14),         \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox15_isr_prio),15),         \
+    },                                                                  \
+    last_tx_id      : 0xFFFFFFFF,                                       \
+    boff_int        : FLEXCAN_INT_INIT(_boff_isr_vec, _boff_isr_prio),  \
+    err_int         : FLEXCAN_INT_INIT(_err_isr_vec, _err_isr_prio),    \
+    wake_int        : FLEXCAN_INT_INIT(_wake_isr_vec, _wake_isr_prio),  \
+    tx_all_mbox     : _tx_all_mbox,                                     \
+    free_mboxes      : ((_std_mboxes) + (_ext_mboxes)),                 \
+    state            : CYGNUM_CAN_STATE_ACTIVE,                         \
+    rx_all           : true,                                            \
+    mboxes_std_cnt   : _std_mboxes,                                     \
+    mboxes_ext_cnt   : _ext_mboxes,                                     \
+    mboxes_rx_all_cnt : ((_std_mboxes) + (_ext_mboxes))                 \
 };
 
 
@@ -302,26 +403,96 @@ flexcan_info _l = {                                                     \
 #define FLEXCAN_MBOX_INTPRIO(n) _FLEXCAN_MBOX_INTPRIO(n)
 
 //
-// FlexCAN channel initialisation
+// Define number of message boxes if they are not defined yet
+//
+#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES
+#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES 0
+#endif
+#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES
+#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES 0
+#endif
+#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES
+#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES 0
+#endif
+#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES
+#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES 0
+#endif
+
+
+#ifdef CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN0
+//
+// FlexCAN channel initialisation for FlexCAN channel 0
 //
 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),
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX0,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX1,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX2,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX3,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX4,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX5,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX6,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX7,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX8,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX9,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX10,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX11,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX12,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX13,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX14,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX15,
              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);
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_ERRINT,
+             HAL_MCF52xx_FLEXCAN0_WAKE_ISRVEC,       
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_WAKEINT,
+             CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_TX_MBOX,
+             CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES,
+             CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES);
+#endif // CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]
+
+#ifdef CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN1
+//
+// FlexCAN channel initialisation for FlexCAN channel 1
+//
+FLEXCAN_INFO(flexcan_can0_info,
+             HAL_MCF52xx_MBAR + HAL_MCF52xx_FLEXCAN0_BASE,
+             HAL_MCF52xx_FLEXCAN1_MBOX0_ISRVEC,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX0,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX1,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX2,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX3,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX4,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX5,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX6,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX7,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX8,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX9,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX10,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX11,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX12,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX13,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX14,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX15,
+             HAL_MCF52xx_FLEXCAN1_BOFF_ISRVEC,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_BOFFINT,
+             HAL_MCF52xx_FLEXCAN1_ERR_ISRVEC,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_ERRINT,
+             HAL_MCF52xx_FLEXCAN1_WAKE_ISRVEC,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_WAKEINT,
+             CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_DEFAULT_TX_MBOX,
+             CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES,
+             CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES);
+#endif // CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN1
 
 //
-// message box structure
+// message box structure for hardware access of message box
 //
 typedef struct flexcan_mbox
 {
-    cyg_uint8  timestamp;
+    cyg_uint8  timestamp; 
     cyg_uint8  ctrlstat;
     cyg_uint16 id_hi;
     cyg_uint16 id_lo;
@@ -330,7 +501,7 @@ typedef struct flexcan_mbox
 } flexcan_mbox;
 
 //
-// flexcan register layout
+// flexcan register layout for hardware register access of FlexCAN modul
 //
 typedef struct flexcan_regs
 {
@@ -382,6 +553,7 @@ static cyg_uint16 flexcan_baud_rates[] = {
 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 Cyg_ErrNo   flexcan_get_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);
@@ -390,10 +562,18 @@ 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);
+#ifdef CYGOPT_IO_CAN_STD_CAN_ID
+static cyg_uint32  flexcan_mbox_rx_std_isr(cyg_vector_t, cyg_addrword_t);
+static void        flexcan_mbox_rx_std_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
+#endif // CYGOPT_IO_CAN_STD_CAN_ID
+#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
+static cyg_uint32  flexcan_mbox_rx_ext_isr(cyg_vector_t, cyg_addrword_t);
+static void        flexcan_mbox_rx_ext_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
+#endif // CYGOPT_IO_CAN_EXT_CAN_ID
+static cyg_uint32  flexcan_mbox_rx_filt_isr(cyg_vector_t, 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);
+static void        flexcan_mbox_rx_filt_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t );
 
 //
 // All other flexcan interrupt handlers
@@ -402,20 +582,37 @@ 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 cyg_uint32  flexcan_wake_isr(cyg_vector_t, cyg_addrword_t);
+static void        flexcan_wake_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
 
-
+//
+// Flexcan utility functions
+//
 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_cfg_mbox_rx(flexcan_mbox *pmbox, cyg_can_message  *pmsg, bool enable);
 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_set_acceptance_mask(cyg_uint16 *rxmask_reg, cyg_uint32 mask, cyg_can_id_type ext);
 static void flexcan_start_chip(can_channel *chan);
+static void flexcan_enter_standby(can_channel *chan, bool selfwake);
+static void flexcan_stop_chip(can_channel *chan);
+static void flexcan_leave_standby(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);
+static cyg_int8 flexcan_alloc_mbox(flexcan_info *info);
+static void flexcan_disable_mbox(can_channel *chan, cyg_uint32 mbox_id);
+static void flexcan_setup_rxmbox(can_channel *chan, cyg_uint32 mbox_id, cyg_ISR_t *isr, cyg_can_message *pmsg, bool enable, bool int_enable);
+static void flexcan_setup_txmbox(can_channel *chan, cyg_uint32 mbox_id, cyg_can_message *pmsg);
+static void flexcan_setup_rtrmbox(can_channel *chan, cyg_uint32 mbox_id, cyg_can_message *pmsg);
+static void flexcan_mboxint_enable(flexcan_info *info, cyg_uint32 mbox_id);
+static void flexcan_mboxint_disable(flexcan_info *info, cyg_uint32 mbox_id);
+static void flexcan_config_rx_all(can_channel *chan);
+static void flexcan_enable_rxmbox(can_channel *chan, cyg_uint32 mbox_id);
 
 
 CAN_LOWLEVEL_FUNS(flexcan_lowlevel_funs,
                   flexcan_putmsg,
                   flexcan_getevent,
+                  flexcan_get_config,
                   flexcan_set_config,
                   flexcan_start_xmit,
                   flexcan_stop_xmit
@@ -459,81 +656,579 @@ flexcan_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab,
 
 
 //===========================================================================
-//  Set device configuration
+// Enable hardware message box for reception
 //===========================================================================
-static Cyg_ErrNo
-flexcan_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len)
+static __inline__  void flexcan_hwmbox_enable_rx(flexcan_regs *flexcan, cyg_uint32 mbox_id)
 {
-    Cyg_ErrNo     res = ENOERR;
+    HAL_WRITE_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), MBOX_RXCODE_EMPTY);
+}
+
+
+//===========================================================================
+// Disable hardware message box
+//===========================================================================
+static __inline__  void flexcan_hwmbox_disable(flexcan_regs *flexcan, cyg_uint32 mbox_id)
+{
+    HAL_WRITE_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), MBOX_RXCODE_NOT_ACTIVE);
+}
+
+
+//===========================================================================
+// lock mbox by reading control status register
+//===========================================================================
+static __inline__  void flexcan_hwmbox_lock(flexcan_regs *flexcan, cyg_uint32 mbox_id, cyg_uint8 *pctrlstat)
+{
+    HAL_READ_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), *pctrlstat); // this read will lock the mbox
+}
+
+
+//===========================================================================
+//  Enable message box interrupt for one message box
+//===========================================================================
+static void flexcan_mboxint_enable(flexcan_info *info, cyg_uint32 mbox_id)
+{
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    
+    info->imask_shadow |= (0x0001 << mbox_id);
+    HAL_WRITE_UINT16(&flexcan->IMASK, info->imask_shadow);
+}
+
+
+//===========================================================================
+//  Disable message box interrupt for one message box
+//===========================================================================
+static void flexcan_mboxint_disable(flexcan_info *info, cyg_uint32 mbox_id)
+{
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
     
-    switch(key) 
+    info->imask_shadow &= ~(0x0001 << mbox_id);
+    HAL_WRITE_UINT16(&flexcan->IMASK, info->imask_shadow);
+}
+
+
+//===========================================================================
+// Allocate message box
+// Try to find a free message box and return its ID
+//===========================================================================
+static cyg_int8 flexcan_alloc_mbox(flexcan_info *info)
+{
+    cyg_uint8     i;
+    cyg_int8      res = CYGNUM_CAN_MSGBUF_NA;
+    
+    if (info->free_mboxes)
+    {  
+        for (i = (FLEXCAN_MBOX_RX_CNT - info->free_mboxes); i <= FLEXCAN_MBOX_RX_MAX; ++i)
+        {
+            if (MBOX_STATE_DISABLED == info->mboxes[i].state)
+            {
+                info->free_mboxes--;
+                res = i;
+                break;
+            }               
+        }
+    } // if (info->free_mboxes)
+    
+    return res;
+}
+
+
+//===========================================================================
+// Enable a previously configured rx mbox - a mbox ready to recive
+//===========================================================================
+static void flexcan_enable_rxmbox(can_channel     *chan,
+                                  cyg_uint32       mbox_id)
+{
+    flexcan_info *info = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+
+    flexcan_hwmbox_enable_rx(flexcan, mbox_id);
+    flexcan_mboxint_enable(info, mbox_id);
+}
+
+//===========================================================================
+// Prepare message buffer filter
+// Setup a RX message box for reception of a certain CAN identifier but do
+// not enable it
+//===========================================================================
+static void flexcan_setup_rxmbox(can_channel     *chan, 
+                                 cyg_uint32       mbox_id,
+                                 cyg_ISR_t       *isr,
+                                 cyg_can_message *pmsg,
+                                 bool             enable,
+                                 bool             int_enable)
+{
+    flexcan_info      *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs      *flexcan = (flexcan_regs *)info->base;
+    flexcan_mbox_info *pmbox;
+    cyg_DSR_t         *dsr_func = &flexcan_mbox_rx_filt_dsr;
+    
+    //
+    // Set state of message buffer accoring to ISR function that
+    // will be registered
+    //
+#ifdef CYGOPT_IO_CAN_STD_CAN_ID
+    if (*isr == flexcan_mbox_rx_std_isr)
     {
-        case CYG_IO_SET_CONFIG_CAN_INFO:
+        //
+        // If we have only one single RX all message box then we use
+        // the filter ISR instead of RX all standard ISR because it
+        // is better suited for a single RX mbox
+    //
+        if (info->mboxes_std_cnt > 1)
+        {
+            info->mboxes[mbox_id].state = MBOX_STATE_RX_ALL_STD;
+            dsr_func = &flexcan_mbox_rx_std_dsr;
+        }
+        else
+        {
+            info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT;
+            isr = flexcan_mbox_rx_filt_isr;
+        }
+    }
+    else
+#endif // CYGOPT_IO_CAN_STD_CAN_ID
+#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
+    if (*isr == flexcan_mbox_rx_ext_isr)
+    {
+        //
+        // If we have only one single RX all message box then we use
+        // the filter ISR instead of RX all standard ISR because it
+        // is better suited for a single RX mbox
+        //
+        if (info->mboxes_ext_cnt > 1)
+        {
+            info->mboxes[mbox_id].state = MBOX_STATE_RX_ALL_EXT;
+            dsr_func = &flexcan_mbox_rx_ext_dsr;
+        }
+        else
+        {
+            info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT;
+            isr = flexcan_mbox_rx_filt_isr;
+        }
+    }
+    else
+#endif // CYGOPT_IO_CAN_EXT_CAN_ID
+    if (*isr == flexcan_mbox_rx_filt_isr)
+    {
+        info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT;
+    }
+    else
+    {
+        CYG_ASSERT(0, "Invalid ISR function pointer");
+    }
+
+    pmbox = &info->mboxes[mbox_id];
+    flexcan_cfg_mbox_rx(&flexcan->mbox[mbox_id], pmsg, enable);
+
+    cyg_drv_interrupt_create(pmbox->isr_vec,
+                             pmbox->isr_priority,
+                             (cyg_addrword_t) chan,
+                             isr,
+                             dsr_func,
+                             &(pmbox->interrupt_handle),
+                             &(pmbox->interrupt));
+    cyg_drv_interrupt_attach(pmbox->interrupt_handle);
+    cyg_drv_interrupt_unmask(pmbox->isr_vec);
+    
+    //
+    // now enable interrupt for this message box - but only if we
+    // really should do it
+    //
+    if (int_enable)
+    {
+    flexcan_mboxint_enable(info, mbox_id);
+    }
+}
+
+
+//===========================================================================
+// Disable a message box - after this call a message box is available
+// again for message filters or remote buffers
+//===========================================================================
+static void flexcan_disable_mbox(can_channel *chan, cyg_uint32 mbox_id)
+{
+    flexcan_info      *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs      *flexcan = (flexcan_regs *)info->base;
+    flexcan_mbox_info *pmbox;
+    
+    //
+    // if message box is already disabled we do not need to disable it
+    // here
+    //
+    if (MBOX_STATE_DISABLED == info->mboxes[mbox_id].state)
+    {
+        return;
+    }
+    
+    HAL_WRITE_UINT8(&flexcan->mbox[mbox_id].ctrlstat, MBOX_RXCODE_NOT_ACTIVE);
+    info->mboxes[mbox_id].state = MBOX_STATE_DISABLED;
+    pmbox = &info->mboxes[mbox_id];
+    
+    //
+    // now disable interrupts for this message box and free all
+    // interrupt resources
+    //
+    flexcan_mboxint_disable(info, mbox_id);
+    cyg_drv_interrupt_mask(pmbox->isr_vec);
+    cyg_drv_interrupt_detach(pmbox->interrupt_handle);
+    cyg_drv_interrupt_delete(pmbox->interrupt_handle);
+    
+    info->free_mboxes++;
+}
+
+
+//===========================================================================
+// Setup a transmit message box
+//===========================================================================
+static void flexcan_setup_txmbox(can_channel      *chan,
+                                 cyg_uint32        mbox_id,
+                                 cyg_can_message  *pmsg)
+{
+    flexcan_info      *info   = (flexcan_info *)chan->dev_priv;
+    flexcan_regs      *flexcan = (flexcan_regs *)info->base;
+    flexcan_mbox_info *pmbox;
+    
+    info->mboxes[mbox_id].state = MBOX_STATE_TX;
+    pmbox = &info->mboxes[mbox_id];
+    flexcan_cfg_mbox_tx(&flexcan->mbox[mbox_id], pmsg, false);
+
+    //
+    // prepare message box interrupt for message box 
+    //
+    cyg_drv_interrupt_create(pmbox->isr_vec,
+                             pmbox->isr_priority,
+                             (cyg_addrword_t) chan,
+                             &flexcan_mbox_tx_isr,
+                             &flexcan_mbox_tx_dsr,
+                             &(pmbox->interrupt_handle),
+                             &(pmbox->interrupt));
+    cyg_drv_interrupt_attach(pmbox->interrupt_handle);
+    cyg_drv_interrupt_unmask(pmbox->isr_vec);
+    
+    //
+    // now enable interrupt for this message box
+    //
+    flexcan_mboxint_enable(info, mbox_id);
+}
+
+
+//===========================================================================
+// Setup a RTR response message box
+//===========================================================================
+static void flexcan_setup_rtrmbox(can_channel      *chan,
+                                  cyg_uint32        mbox_id,
+                                  cyg_can_message  *pmsg)
+{
+    flexcan_info      *info   = (flexcan_info *)chan->dev_priv;
+    flexcan_regs      *flexcan = (flexcan_regs *)info->base;
+    
+    info->mboxes[mbox_id].state = MBOX_STATE_REMOTE_TX;
+    flexcan_cfg_mbox_tx(&flexcan->mbox[mbox_id], pmsg, true);
+}
+
+
+//===========================================================================
+// Setup the list of message boxes ready to receive a message
+//===========================================================================
+static void flexcan_setup_rxmbox_circbuf(flexcan_rxmbox_circbuf *pbuf)
+{
+    pbuf->count  = 0;
+    pbuf->idx_rd = 0;
+    pbuf->idx_wr = 0;
+}
+
+
+//===========================================================================
+// Setup flexCAN modul for reception of any kind of message
+//===========================================================================
+static void flexcan_config_rx_all(can_channel *chan)
+{
+    flexcan_info *info       = (flexcan_info *)chan->dev_priv;
+    flexcan_regs       *flexcan = (flexcan_regs *)info->base;
+    cyg_int8           i;
+    
+        //
+    // setup all available message boxes for reception of of messages
+    // All standard and extended message buffers will be configured
+        //
+    for (i = 0; i < info->mboxes_rx_all_cnt; ++i)
              {
-                 cyg_can_info_t*  config = (cyg_can_info_t*) buf;
-                 if (*len < sizeof(cyg_can_info_t)) 
+        cyg_can_message filter_param;
+        filter_param.id  = 0;
+
+        //
+        // configure message buffers for standard frames
+        //
+#ifdef CYGOPT_IO_CAN_STD_CAN_ID
+        if (i < info->mboxes_std_cnt)
                  {
-                    return -EINVAL;
+            filter_param.ext = CYGNUM_CAN_ID_STD;
+            flexcan_setup_rxmbox(chan, i, &flexcan_mbox_rx_std_isr, &filter_param, false, true);
                  }
-                 *len = sizeof(cyg_can_info_t);
-                 if (!flexcan_config(chan, config, false)) 
+#endif // CYGOPT_IO_CAN_STD_CAN_ID
+
+       //
+       // configure message buffers for extended frames
+       //
+#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
+        else
                  {
-                    return -EINVAL;
+            filter_param.ext = CYGNUM_CAN_ID_EXT;
+            flexcan_setup_rxmbox(chan, i, &flexcan_mbox_rx_ext_isr, &filter_param, false, true);
                  }
+#endif // CYGOPT_IO_CAN_EXT_CAN_ID
             }
-            break;
-            
-        case CYG_IO_SET_CONFIG_CAN_RTR_BUF:
+       
+        //
+    // We need to receive all available CAN messages so we have to set the acceptance filter
+    // properly
+    //
+    flexcan_set_acceptance_mask(&flexcan->RXGMASK_HI,  FLEXCAN_ACCEPTANCE_MASK_RX_ALL,  CYGNUM_CAN_ID_EXT);
+    flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, FLEXCAN_ACCEPTANCE_MASK_RX_ALL, CYGNUM_CAN_ID_EXT);
+    info->free_mboxes = FLEXCAN_MBOX_RX_CNT - info->mboxes_rx_all_cnt;
+    info->rx_all = true;
+
+    //
+    // now finally setup the first active message boxes and enable ist
+        //     
+#ifdef CYGOPT_IO_CAN_STD_CAN_ID
+    if (info->mboxes_std_cnt)
              { 
-                 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)) 
+        flexcan_setup_rxmbox_circbuf(&info->rxmbox_std_circbuf);
+        flexcan_enable_rxmbox(chan, 0);
+    }
+#endif // CYGOPT_IO_CAN_STD_CAN_ID
+                             
+#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
+    if (info->mboxes_ext_cnt)
                  {
-                    return -EINVAL;
+        flexcan_setup_rxmbox_circbuf(&info->rxmbox_ext_circbuf);
+        flexcan_enable_rxmbox(chan, info->mboxes_std_cnt);
                  }
-                 *len = sizeof(cyg_can_rtr_buf_t);
+#endif // CYGOPT_IO_CAN_EXT_CAN_ID
+
+}
+
+//===========================================================================
+// Setup Flex CAN moduls in a state where all message boxes are disabled
+// After this call single message filters and buffers can be added
+//===========================================================================
+static void flexcan_config_rx_none(can_channel *chan)
+{
+    flexcan_info       *info = (flexcan_info *)chan->dev_priv;
+    flexcan_regs       *flexcan = (flexcan_regs *)info->base;
+    cyg_int8           i;
                  
                  //
-                 // 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
+    // setup all RX messages moxes into a disabled state
                  //
-                 if (CYGNUM_CAN_RTR_BUF_INIT == rtr_buf->handle)
+    for (i = 0; i < FLEXCAN_MBOX_RX_CNT; ++i)
                  {
-                    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;
+        flexcan_disable_mbox(chan, i);
+    }
+                     
+    //
+    // If we want to receive only certain CAN identiffiers then the ID does matter and
+    // we have to setup the acceptance mask properly
+    //
+    flexcan_set_acceptance_mask(&flexcan->RXGMASK_HI,  FLEXCAN_ACCEPTANCE_MASK_RX_ID,  CYGNUM_CAN_ID_EXT);
+    flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, FLEXCAN_ACCEPTANCE_MASK_RX_ID,  CYGNUM_CAN_ID_EXT);
+    info->free_mboxes = FLEXCAN_MBOX_RX_CNT;
+    info->rx_all = false;
+}
+
+
+//===========================================================================
+// Configure message buffers
+//===========================================================================
+static Cyg_ErrNo flexcan_set_config_msgbuf(can_channel *chan, cyg_can_msgbuf_cfg *buf)
+{
+    Cyg_ErrNo     res = ENOERR;
+    flexcan_info *info = (flexcan_info *)chan->dev_priv;
+
+    switch (buf->cfg_id)
+                     {
+                         //
+        // clear all message filters and remote buffers - prepare for message buffer
+        // configuration
+                         //
+        case CYGNUM_CAN_MSGBUF_RESET_ALL :
+                     {
+                 flexcan_config_rx_none(chan);
+                     }
+            break;
+
+                     //
+        // setup FlexCAN modul for reception of all standard and extended messages
+                     //
+        case CYGNUM_CAN_MSGBUF_RX_FILTER_ALL :
+                     {
+                if (!info->rx_all) // if rx_all is enabled we do not need to do anything
+                     {
+                    flexcan_config_rx_none(chan); // set into default state
+                    flexcan_config_rx_all(chan);  // setup RX all state
                      }
-                 } // if (CYGNUM_CAN_RTR_BUF_INIT == rtr_buf->handle)
+             }
+             break;
+        
+        //
+        // add single message filter, message with filter ID will be received
+        //     
+        case CYGNUM_CAN_MSGBUF_RX_FILTER_ADD :
+             {
+                 cyg_can_filter *filter   = (cyg_can_filter*) buf;
                  
                  //
-                 // If we have a valid rtr buf handle then we can store data into 
-                 // rtr message box
+                 // if FlexCAN is configured to receive all messages then it is not
+                 // allowed to add single message filters because then more than
+                 // one message buffer would receive the same CAN id
+                 //
+                 if (info->rx_all)
+                 {
+                    return -EPERM;
+                 }
+                 
+                 //
+                 // try to allocate a free message box - if we have a free one
+                 // then we can prepare the message box for reception of the
+                 // desired message id
+                 //
+                 filter->handle = flexcan_alloc_mbox(info);
+                 if (filter->handle > CYGNUM_CAN_MSGBUF_NA)
+                 {
+                     flexcan_setup_rxmbox(chan, filter->handle, &flexcan_mbox_rx_filt_isr, &filter->msg, true, true);
+                 }
+             }
+             break; //CYGNUM_CAN_MSGBUF_RX_FILTER_ADD
+
+                     //
+        // Try to add a new RTR response message buffer for automatic transmisson
+        // of data frame on reception of a remote frame
+                     //
+        case CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD :
+                     {
+                 cyg_can_remote_buf *rtr_buf    = (cyg_can_remote_buf*) buf;
+                 rtr_buf->handle = flexcan_alloc_mbox(info);
+                     
+                 if (rtr_buf->handle > CYGNUM_CAN_MSGBUF_NA)
+                     {
+                     //
+                     // if we have a free message buffer then we setup this buffer
+                     // for remote frame reception
+                     //
+                     flexcan_setup_rtrmbox(chan, rtr_buf->handle, &rtr_buf->msg);
+                 }
+                     }
+             break;
+                     
+                     //
+        // write data into remote response buffer
+        //
+        case CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE :
+             {
+                 cyg_can_remote_buf *rtr_buf    = (cyg_can_remote_buf*) buf;
+
                  //
-                 if ((rtr_buf->handle >= 0) && (rtr_buf->handle < 14))
+                 // 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 <= FLEXCAN_MBOX_RX_MAX))
                  {
+                     flexcan_regs *flexcan = (flexcan_regs *)info->base;
                      flexcan_cfg_mbox_tx(&flexcan->mbox[rtr_buf->handle], &rtr_buf->msg, true);
                  }
                  else
                  {
                     return -EINVAL;
+                 }    
+             }
+             break;
+    } // switch (buf->cfg_id)
+        
+     return res;
+}
+
+//===========================================================================
+// 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)
+             {
+                 //
+        //Setup a new CAN configuration. This will i.e. setup a new baud rate
+                 //
+        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;
                  
+                 //
+        // configure message buffers
+                 //
+        case CYG_IO_SET_CONFIG_CAN_MSGBUF :
+             {
+                cyg_can_msgbuf_cfg *msg_buf = (cyg_can_msgbuf_cfg *) buf;
+
+                if (*len != sizeof(cyg_can_msgbuf_cfg))
+                {
+                    return -EINVAL;
+                }
+
+                flexcan_set_config_msgbuf(chan, msg_buf);
              }
              break;
-         
+        
+        //
+        // Change CAN state of FlexCAN modul. This function will set the FlexCAN
+        // modul into STOPPED, ACTIVE or STANDBY state
+        //    
+        case CYG_IO_SET_CONFIG_CAN_MODE :
+             {
+                cyg_can_mode   *can_mode  = (cyg_can_mode*) buf;
+                
+                if (*len != sizeof(cyg_can_mode)) 
+                {
+                    return -EINVAL;
+                }
+                *len = sizeof(cyg_can_mode);
+                
+                //
+                // decide what to do acording to mode
+                //
+                switch (*can_mode)
+                {
+                    case CYGNUM_CAN_MODE_STOP :      // stop FlexCANm modul
+                         flexcan_stop_chip(chan);
+                         break;
+                         
+                    case CYGNUM_CAN_MODE_START :     // start FlexCAN modul
+                         flexcan_leave_standby(chan);
+                         break;
+                          
+                    case CYGNUM_CAN_MODE_STANDBY :   // set FlexCAN modul into standby state
+                         flexcan_enter_standby(chan, true);
+                         break;
+                         
+                    case CYGNUM_CAN_MODE_CONFIG : // stop FlexCAN modul for configuration
+                        flexcan_stop_chip(chan);
+                        break;
+                }
+             }
+             break; // case CYG_IO_SET_CONFIG_CAN_MODE :         
     } // switch (key)
     
     return res;
@@ -541,58 +1236,170 @@ flexcan_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint3
 
 
 //===========================================================================
-//  Read one event from can hardware
+//  Query device configuration
 //===========================================================================
-static bool flexcan_getevent(can_channel *chan, cyg_can_event *pevent, void *pdata)
+static Cyg_ErrNo
+flexcan_get_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len)
 {
-    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)
-    {   
+    Cyg_ErrNo     res  = ENOERR;
+    flexcan_info *info = (flexcan_info *)chan->dev_priv;
+    
+    switch(key)
+    {
         //
-        // read data from message box - during processing of this function
-        // the message box is locked and cannot receive further messages
+        // query state of CAN controller
         //
-        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
+        case CYG_IO_GET_CONFIG_CAN_STATE :
+             {
+                cyg_can_state *can_state  = (cyg_can_state*) buf;
+                
+                if (*len != sizeof(cyg_can_state)) 
+                {
+                    return -EINVAL;
+                }
+                *len = sizeof(cyg_can_state);
+                *can_state = info->state;
+             }
+             break;
+        
         //
-        // 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
+        // Query message box information - returns available and free message
+        // boxes
+        //     
+        case CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO :
+             {
+                 cyg_can_msgbuf_info *mbox_info  = (cyg_can_msgbuf_info*) buf;
+                
+                 if (*len != sizeof(cyg_can_msgbuf_info)) 
+                 {
+                     return -EINVAL;
+                 }
+                *len = sizeof(cyg_can_msgbuf_info);
+                
+                 mbox_info->count = FLEXCAN_MBOX_RX_CNT;
+                 mbox_info->free  = info->free_mboxes;
+             }
+             break;
+        
         //
-        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;
+        // Query hardware description of FlexCAN device driver
+        //     
+        case CYG_IO_GET_CONFIG_CAN_HDI :
+             {
+                cyg_can_hdi *hdi = (cyg_can_hdi *)buf;
+                //
+                // comes from high level driver so we do not need to
+                // check buffer size here
+                //             
+                hdi->support_flags = CYGNUM_CAN_HDI_FRAMETYPE_EXT_ACTIVE
+                                   | CYGNUM_CAN_HDI_FULLCAN;
+#ifdef CYGOPT_IO_CAN_SUPPORT_TIMESTAMP 
+                hdi->support_flags |= CYGNUM_CAN_HDI_TIMESTAMP;
 #endif
+             }
+             break;
+             
+        default :
+            res = -EINVAL;
+    }// switch(key)
     
+    return res;
+} 
+
+
+//===========================================================================
+//  Check if we received self transmitted frame
+//===========================================================================
+static bool flexcan_is_no_self_tx(cyg_can_event *pevent, flexcan_info *info, flexcan_mbox_info *pmbox)
+{
+    //
+    // If 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
+        return false;
+    }
+    else
+    {
+        pevent->flags |= CYGNUM_CAN_EVENT_RX;
+
         //
         // check if an overun occured in this message box
         //
-        if ((mbox_ctrlstat & MBOX_RXCODE_OVERRUN) == MBOX_RXCODE_OVERRUN)
+        if ((pmbox->ctrlstat_shadow & MBOX_RXCODE_OVERRUN) == MBOX_RXCODE_OVERRUN)
         {
             pevent->flags |= CYGNUM_CAN_EVENT_OVERRUN_RX;
         }
+
+        return true;
+    }
+}
+
+
+//===========================================================================
+//  Read one event from can hardware - called from high level I/O CAN driver
+//===========================================================================
+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;
+    bool          res            = true;
+    cyg_uint16    estat;
+    cyg_uint8     event_id       = *((cyg_uint8 *)pdata);
+     
+    //   
+    // if event_id is 0 - 15 the we have a message box event
+    //
+    if (event_id < FLEXCAN_ERR_EVENT)
+    {   
+        flexcan_mbox_info *pmbox_info;
+        pmbox_info = &info->mboxes[event_id];
+        
+        //
+        // Deceide what to do according to type of message box that caused this event
+        //
+        switch (pmbox_info->state)
+        {
+            //
+            // If we have an RX event then we need to read the received data from
+            // message box that caused this event and fill it into message queue of
+            // high level I/O CAN driver. We could handle this stuff in a function
+            // because it is the same like MBOX_STATE_RX_ALL_EXT but speed is more
+            // important here than codesize
+            //
+            case MBOX_STATE_RX_ALL_STD:
+            case MBOX_STATE_RX_ALL_EXT:
+            case MBOX_STATE_RX_FILT:
+            {
+                 //
+                 // 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, &(pmbox_info->ctrlstat_shadow));
+                 res = flexcan_is_no_self_tx(pevent, info, pmbox_info);
+                 }
+                 break;           
+
+#ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT
+            //
+            // If a TX message box cause the event then we store the last transmitted
+            // message into the receive message queue
+            //
+            case MBOX_STATE_TX:  
+                 pevent->flags = CYGNUM_CAN_EVENT_TX;
+                 pevent->msg = info->last_tx_msg;
+                 break;
+#endif // CYGOPT_IO_CAN_TX_EVENT_SUPPORT
+                            
+            case MBOX_STATE_REMOTE_TX:
+                 break;
+                 
+            default:
+                 res = false;
+        } // switch (pmbox->state)
     }
     else // (event_id >= FLEXCAN_ERR_EVENT)
     {
@@ -601,10 +1408,10 @@ static bool flexcan_getevent(can_channel *chan, cyg_can_event *pevent, void *pda
         // 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]);
+        pevent->msg.data.bytes[0] = estat & 0xFF;
+        pevent->msg.data.bytes[1] = (estat >> 8) & 0xFF; 
+        HAL_READ_UINT8(&flexcan->RXERRCNT, pevent->msg.data.bytes[2]);
+        HAL_READ_UINT8(&flexcan->TXERRCNT, pevent->msg.data.bytes[3]);
         switch (event_id)
         {
             case FLEXCAN_ERR_EVENT :
@@ -643,9 +1450,13 @@ static bool flexcan_getevent(can_channel *chan, cyg_can_event *pevent, void *pda
             case FLEXCAN_BUSOFF_EVENT:
                  pevent->flags = CYGNUM_CAN_EVENT_BUS_OFF;
                  break;
+                 
+            case FLEXCAN_WAKE_EVENT:
+                 pevent->flags = CYGNUM_CAN_EVENT_LEAVING_STANDBY;
+                 break;
         } // switch (event_id)
     }
-
+    
     return res;
 }
 
@@ -655,23 +1466,22 @@ static bool flexcan_getevent(can_channel *chan, cyg_can_event *pevent, void *pda
 //===========================================================================
 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;
+    flexcan_info      *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs      *flexcan = (flexcan_regs *)info->base;
+    cyg_uint8          mbox    = *((cyg_uint8 *)pdata);
+    flexcan_mbox_info *pmbox   = &info->mboxes[mbox];
+    cyg_uint16         iflag;
    
     HAL_READ_UINT16(&flexcan->IFLAG, iflag);
     
     //
     // check if device is busy sending a message
     //
-    if (info->tx_busy)
+    if (pmbox->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 device is busy and the interrupt flag is set, then we know
+        // that device is not busy any longer
         //
         if (iflag & (0x0001 << mbox))
         {
@@ -683,58 +1493,69 @@ static bool flexcan_putmsg(can_channel *chan, cyg_can_message *pmsg, void *pdata
         }
     }
     
-    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);
+    pmbox->busy    = true;        // mark transmitter as busy
+    info->last_tx_id  = pmsg->id; // store message in order to identify self recieved frames 
+
+#ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT 
+    info->last_tx_msg = *pmsg;    // store the transmitted message for TX events
+#endif  
+  
+    flexcan_cfg_mbox_tx(&flexcan->mbox[mbox], pmsg, false); // send message
     
     return true;
 }
 
 
 //===========================================================================
-// Flexcan start xmit
+// Flexcan start xmit - If the chip is in standby mode then a call to this
+// function will cause the FlexCAN modul to leave the standby mode. So
+// the output queue should be empty before entering stadby mode
 //===========================================================================
 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;
+    flexcan_info         *info    = (flexcan_info *)chan->dev_priv;
+    CYG_INTERRUPT_STATE   saved_state;
 
     HAL_DISABLE_INTERRUPTS(saved_state);
     
+    //
+    // if we are in standby state the we leave standby state now. This is
+    // the reason that the user should wait until the TX queue is empty before 
+    // entering standby mode- or he should drain or flush the TX queue
+    //
+    if (CYGNUM_CAN_STATE_STANDBY == info->state)
+    {
+        flexcan_leave_standby(chan);
+    }
+    
     //
     // Now enable message box 15 interrupts
     //
-    HAL_READ_UINT16(&flexcan->IMASK, imask);
-    HAL_WRITE_UINT16(&flexcan->IMASK, imask | (0x0001 << info->tx_mbox.num));
+    flexcan_mboxint_enable(info, info->tx_all_mbox);
     
     //
     // kick transmitter
     //
-    chan->callbacks->xmt_msg(chan, &info->tx_mbox.num);  // Kick transmitter (if necessary)
+    chan->callbacks->xmt_msg(chan, &info->tx_all_mbox);  // Kick transmitter (if necessary)
     
     HAL_RESTORE_INTERRUPTS(saved_state);
 }
 
 
 //===========================================================================
-// Flexcan start xmit
+// Flexcan stop transmission
 //===========================================================================
 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;
+    flexcan_info         *info    = (flexcan_info *)chan->dev_priv;
+    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));
+    flexcan_mboxint_disable(info, info->tx_all_mbox);
 
     HAL_RESTORE_INTERRUPTS(saved_state);
 }
@@ -745,12 +1566,21 @@ static void flexcan_stop_xmit(can_channel* chan)
 //===========================================================================
 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;
+    flexcan_info    *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs    *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16       tmp16;
+    cyg_uint8        tmp8;
+    cyg_uint8        i;
+    
+    //
+    // the first thing we need to do is to stop the chip
+    //
+    flexcan_stop_chip(chan);  
     
+    //
+    // if this is the first initialisation of the FlexCAN modul we need to execute
+    // some extra steps here
+    //
     if (init)
     {
 #if defined(CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN0) && defined(HAL_MCF52xx_FLEXCAN0_PROC_INIT)
@@ -788,67 +1618,43 @@ static bool flexcan_config(can_channel* chan, cyg_can_info_t* config, cyg_bool i
                                             & ~FLEXCAN_CTRL0_ERRMASK);
                                             
         //
-        // setup message box acceptance filter
+        // deactivate all message buffers - this is mandatory for configuration
+        // of message buffers
         //
-        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));
+        for (i = FLEXCAN_MBOX_MIN; i <= FLEXCAN_MBOX_MAX; ++i)
+        {
+            HAL_WRITE_UINT16(&flexcan->mbox[i], MBOX_RXCODE_NOT_ACTIVE);
+        }   
         
-    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));
+        //
+        // mask all interrupts
+        //
+        info->imask_shadow = 0x0000;
+        HAL_WRITE_UINT16(&flexcan->IMASK, info->imask_shadow);
+        HAL_READ_UINT8(&flexcan->CANCTRL0, tmp8);
+        HAL_WRITE_UINT8(&flexcan->CANCTRL0, tmp8 & ~(FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));    
+        
+        //
+        // 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));    
+        
+        //
+        // setup all rx message buffers
+        //
+        flexcan_config_rx_all(chan);
     
-    //
-    // now we can start the chip
-    //
-    flexcan_start_chip(chan);
+        //
+        // bus off interrupt and error interrupt
+        //
+        HAL_READ_UINT8(&flexcan->CANCTRL0, tmp8);
+        HAL_WRITE_UINT8(&flexcan->CANCTRL0, tmp8 | (FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));                             
+    } // if (init)
+                      
+    flexcan_set_baud(chan, config->baud); // setup baud rate
     
     //
     // store new config values
@@ -857,50 +1663,38 @@ static bool flexcan_config(can_channel* chan, cyg_can_info_t* config, cyg_bool i
     {
         chan->config = *config;
     }
+    flexcan_start_chip(chan);             // now we can start the chip again
     
     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;
+    can_channel       *chan    = (can_channel*)devtab_entry->priv;
+    flexcan_info      *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_mbox_info *pmbox;
 
     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,
+    pmbox = &info->mboxes[info->tx_all_mbox];
+    cyg_drv_interrupt_create(pmbox->isr_vec,
+                             pmbox->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);
+                             &(pmbox->interrupt_handle),
+                             &(pmbox->interrupt));
+    cyg_drv_interrupt_attach(pmbox->interrupt_handle);
+    cyg_drv_interrupt_unmask(pmbox->isr_vec);
     
     //
     // prepare error interrupt
@@ -927,6 +1721,19 @@ static bool flexcan_init(struct cyg_devtab_entry* devtab_entry)
                              &(info->boff_int.interrupt));
     cyg_drv_interrupt_attach(info->boff_int.interrupt_handle);
     cyg_drv_interrupt_unmask(info->boff_int.isr_vec);
+    
+    //
+    // prepare wake interrupt
+    //
+    cyg_drv_interrupt_create(info->wake_int.isr_vec,
+                             info->wake_int.isr_priority,
+                             (cyg_addrword_t) chan,
+                             &flexcan_wake_isr,
+                             &flexcan_wake_dsr,
+                             &(info->wake_int.interrupt_handle),
+                             &(info->wake_int.interrupt));
+    cyg_drv_interrupt_attach(info->wake_int.interrupt_handle);
+    cyg_drv_interrupt_unmask(info->wake_int.isr_vec);
         
     return true;
 }
@@ -995,19 +1802,78 @@ static void flexcan_err_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t
 //===========================================================================
 // Bus off interrupt handler
 //===========================================================================
-static cyg_uint32  flexcan_busoff_isr(cyg_vector_t vec, cyg_addrword_t data)
+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);  
+}
+
+
+//===========================================================================
+// Bus off interrupt handler
+//===========================================================================
+static cyg_uint32  flexcan_wake_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
+    // first we disable wake interrupts - we set the mcr register to
+    // zero in order to bring it back to normal state
     //
-    HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
-    HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 & ~FLEXCAN_CTRL0_BOFFMSK);
+    HAL_WRITE_UINT16(&flexcan->CANMCR, 0);
     
     //
     // for clearing the interrupt we first read the flag register as 1
@@ -1016,8 +1882,8 @@ static cyg_uint32  flexcan_busoff_isr(cyg_vector_t vec, cyg_addrword_t data)
     // message box interrupts untouched
     //
     HAL_READ_UINT16(&flexcan->ESTAT, estat);
-    HAL_WRITE_UINT16(&flexcan->ESTAT, FLEXCAN_ESTAT_BOFFINT);  
-    
+    HAL_WRITE_UINT16(&flexcan->ESTAT, FLEXCAN_ESTAT_WAKEINT);
+       
     //
     // On the mcf5272 there is no need to acknowledge internal
     // interrupts, only external ones.
@@ -1030,38 +1896,42 @@ static cyg_uint32  flexcan_busoff_isr(cyg_vector_t vec, cyg_addrword_t data)
 //===========================================================================
 // 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)
+static void flexcan_wake_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     event_id = FLEXCAN_WAKE_EVENT;
     cyg_uint8     ctrl0;
-    cyg_uint8     event_id = FLEXCAN_BUSOFF_EVENT;
 
     //
     // signal CAN event to generic IO CAN driver - it will do any further 
-    // processing
+    // processing we will enable all other interrupts after the call to 
+    // rcv_event because the user should receive this event as the first
+    // event after FlexCAN leaves standby.
     //            
     chan->callbacks->rcv_event(chan, &event_id);
     
     //
-    // reenable bus off interrupts
+    // for standby we disabled all interrut source so we have to enable
+    // it here again for normal operation
     //
+    HAL_WRITE_UINT16(&flexcan->IMASK, info->imask_shadow);
     HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
-    HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 | FLEXCAN_CTRL0_BOFFMSK);  
+    HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 |(FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));
 }
 
 
 //===========================================================================
-// Flexcan message box isr
+// Flexcan message box isr for rx messages if message filtering is
+// enabled
 //===========================================================================
-static cyg_uint32 flexcan_mbox_rx_isr(cyg_vector_t vec, cyg_addrword_t data)
+static cyg_uint32 flexcan_mbox_rx_filt_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
@@ -1074,8 +1944,8 @@ static cyg_uint32 flexcan_mbox_rx_isr(cyg_vector_t vec, cyg_addrword_t data)
     // 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));
+    flexcan_mboxint_disable(info, mbox);
+    info->mboxes[mbox].ctrlstat_shadow = FLEXCAN_CTRLSTAT_NOT_READ;
     
     //
     // for clearing the interrupt we first read the flag register as 1
@@ -1095,15 +1965,246 @@ static cyg_uint32 flexcan_mbox_rx_isr(cyg_vector_t vec, cyg_addrword_t data)
 }
 
 
+#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
 //===========================================================================
-// Flexcan message box dsr
+// Flexcan message box isr for extended identifiers if reception of all
+// available messages is enabled
+//===========================================================================
+static cyg_uint32 flexcan_mbox_rx_ext_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;
+    flexcan_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_ext_circbuf);
+
+    //
+    // number of message box can be calculated from vector that caused
+    // 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;
+    if (++prx_mbox_list->count < info->mboxes_ext_cnt)
+    {
+        prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_ext_cnt;
+        flexcan_hwmbox_enable_rx(flexcan, prx_mbox_list->idx_wr + info->mboxes_std_cnt);
+        flexcan_hwmbox_lock(flexcan, mbox, &(info->mboxes[mbox].ctrlstat_shadow));
+        flexcan_hwmbox_disable(flexcan, mbox);  // now disable this message box - it is already locked
+        //
+        // first we disable interrupts of this message box - the DSR will
+        // reenable it later
+        //
+        flexcan_mboxint_disable(info, mbox);
+    }
+    else
+    {
+        prx_mbox_list->count = info->mboxes_ext_cnt;
+        info->mboxes[mbox].ctrlstat_shadow = FLEXCAN_CTRLSTAT_NOT_READ;
+    }
+
+    //
+    // 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); If counter of mbox list is > 1
+    // then we know that there is already a DSR running and we do not
+    // need to invoke one
+    //
+    if (prx_mbox_list->count > 1)
+    {
+        return CYG_ISR_HANDLED;
+    }
+    else
+    {
+        return CYG_ISR_CALL_DSR;
+    }
+}
+
+
+//===========================================================================
+// FlexCAN message box DSR for extended CAN frames
+//===========================================================================
+static void flexcan_mbox_rx_ext_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_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_ext_circbuf);
+    cyg_uint8               mbox;
+    cyg_uint8               mbox_cnt;
+
+    //
+    // we do not process the message box we received as event_id
+    // we take the message boxes from the ring buffer
+    //
+    do
+    {
+        cyg_drv_isr_lock();
+        mbox_cnt = --prx_mbox_list->count;
+        cyg_drv_isr_unlock();
+
+        mbox = prx_mbox_list->idx_rd + info->mboxes_std_cnt;
+        prx_mbox_list->idx_rd = (prx_mbox_list->idx_rd + 1) % info->mboxes_ext_cnt;
+        chan->callbacks->rcv_event(chan, &mbox);
+        flexcan_mboxint_enable(info, mbox);
+
+        //
+        // if the last message box is enabled, then we have to enable
+        // another one now because the last message box is filled already
+        //
+        if (mbox_cnt == (info->mboxes_ext_cnt - 1))
+        {
+            cyg_uint8     active_mbox;
+            cyg_uint8     next_mbox;
+            flexcan_regs *flexcan = (flexcan_regs *)info->base;
+
+            cyg_drv_isr_lock();
+            active_mbox = prx_mbox_list->idx_wr;
+            next_mbox = prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_ext_cnt;
+            cyg_drv_isr_unlock();
+
+            active_mbox += info->mboxes_std_cnt;
+            next_mbox += info->mboxes_std_cnt;
+            flexcan_hwmbox_lock(flexcan, active_mbox, &(info->mboxes[active_mbox].ctrlstat_shadow));
+            flexcan_hwmbox_disable(flexcan, active_mbox);  // now disable this message box - it is already locked
+            flexcan_hwmbox_enable_rx(flexcan, next_mbox);
+        }
+    }
+    while (mbox_cnt);
+}
+
+#endif // #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
+
+
+#ifdef CYGOPT_IO_CAN_STD_CAN_ID
+//===========================================================================
+// Flexcan message box isr for standard identifiers if reception of all
+// available messages is enabled
+//===========================================================================
+static cyg_uint32 flexcan_mbox_rx_std_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;
+    flexcan_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_std_circbuf);
+
+    //
+    // number of message box can be calculated from vector that caused
+    // 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;
+    if (++prx_mbox_list->count < info->mboxes_std_cnt)
+    {
+        prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_std_cnt;
+        flexcan_hwmbox_enable_rx(flexcan, prx_mbox_list->idx_wr);
+        flexcan_hwmbox_lock(flexcan, mbox, &(info->mboxes[mbox].ctrlstat_shadow));
+        flexcan_hwmbox_disable(flexcan, mbox);  // now disable this message box - it is already locked
+        //
+        // first we disable interrupts of this message box - the DSR will
+        // reenable it later
+        //
+        flexcan_mboxint_disable(info, mbox);
+    }
+    else
+    {
+        prx_mbox_list->count = info->mboxes_std_cnt;
+        info->mboxes[mbox].ctrlstat_shadow = FLEXCAN_CTRLSTAT_NOT_READ;
+    }
+
+    //
+    // 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); If counter of mbox list is > 1
+    // then we know that there is already a DSR running and we do not
+    // need to invoke one
+    //
+    if (prx_mbox_list->count > 1)
+    {
+        return CYG_ISR_HANDLED;
+    }
+    else
+    {
+        return CYG_ISR_CALL_DSR;
+    }
+}
+
+
+//===========================================================================
+// Flexcan message box dsr for standard CAN frames
+//===========================================================================
+static void flexcan_mbox_rx_std_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_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_std_circbuf);
+    cyg_uint8               mbox;
+    cyg_uint8               mbox_cnt;
+
+    //
+    // we do not process the message box we received as event_id
+    // we take the message boxes from the ring buffer
+    //
+    do
+    {
+        cyg_drv_isr_lock();
+        mbox_cnt = --prx_mbox_list->count;
+        cyg_drv_isr_unlock();
+
+        mbox = prx_mbox_list->idx_rd;
+        prx_mbox_list->idx_rd = (prx_mbox_list->idx_rd + 1) % info->mboxes_std_cnt;
+        chan->callbacks->rcv_event(chan, &mbox);
+        flexcan_mboxint_enable(info, mbox);
+
+        //
+        // if the last message box is enabled, then we have to enable
+        // another one now because the last message box is filled already
+        //
+        if (mbox_cnt == (info->mboxes_std_cnt - 1))
+        {
+            cyg_uint8     active_mbox;
+            cyg_uint8     next_mbox;
+            flexcan_regs *flexcan = (flexcan_regs *)info->base;
+
+            cyg_drv_isr_lock();
+            active_mbox = prx_mbox_list->idx_wr;
+            next_mbox = prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_ext_cnt;
+            cyg_drv_isr_unlock();
+
+            flexcan_hwmbox_lock(flexcan, active_mbox, &(info->mboxes[active_mbox].ctrlstat_shadow));
+            flexcan_hwmbox_disable(flexcan, active_mbox);  // now disable this message box - it is already locked
+            flexcan_hwmbox_enable_rx(flexcan, next_mbox);
+        }
+    }
+    while (mbox_cnt);
+}
+#endif // CYGOPT_IO_CAN_STD_CAN_ID
+
+
 //===========================================================================
-static void flexcan_mbox_rx_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
+// FlexCAN DSR for message filters
+//===========================================================================
+static void flexcan_mbox_rx_filt_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
@@ -1117,12 +2218,11 @@ static void flexcan_mbox_rx_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrwo
     // 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_mboxint_enable(info, mbox);
 }
 
 //===========================================================================
@@ -1130,11 +2230,10 @@ static void flexcan_mbox_rx_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrwo
 //===========================================================================
 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;
+    can_channel       *chan    = (can_channel *)data;
+    flexcan_info      *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs      *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16         iflag;
     
     // number of message box can be calculated from vector that cause
     // interrupt - we pass this message box number as additional data to the
@@ -1155,8 +2254,7 @@ static cyg_uint32 flexcan_mbox_tx_isr(cyg_vector_t vec, cyg_addrword_t data)
     // 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));
+    flexcan_mboxint_disable(info, mbox);
     
     //
     // for clearing the interrupt we first read the flag register as 1
@@ -1165,8 +2263,7 @@ static cyg_uint32 flexcan_mbox_tx_isr(cyg_vector_t vec, cyg_addrword_t data)
     // message box interrupts untouched
     //
     HAL_READ_UINT16(&flexcan->IFLAG, iflag);
-    HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox)); 
-    info->tx_busy = false;   
+    HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));   
     
     //
     // On the mcf5272 there is no need to acknowledge internal
@@ -1182,18 +2279,28 @@ static cyg_uint32 flexcan_mbox_tx_isr(cyg_vector_t vec, cyg_addrword_t data)
 //===========================================================================
 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;
+    can_channel       *chan    = (can_channel *)data;
+    flexcan_info      *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_mbox_info *pmbox;
     
     //
     // 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;    
+    cyg_uint8 mbox = vec - info->isr_vec_mbox0; 
+    pmbox = &info->mboxes[mbox];
+    
+#ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT 
+    //
+    // signal CAN TX event to generic IO CAN driver - it will do any further 
+    // processing
+    //            
+    chan->callbacks->rcv_event(chan, &mbox);
+#endif
     
+    pmbox->busy = false;
+       
     //
     // send next message 
     //            
@@ -1202,13 +2309,12 @@ static void flexcan_mbox_tx_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrwo
     //
     // 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_mboxint_enable(info, mbox);
 }
 
 
 //===========================================================================
-//                     START FLEXCAN MODUL
+// Start FlexCAN modul
 //===========================================================================
 static void flexcan_start_chip(can_channel *chan)
 {
@@ -1216,6 +2322,8 @@ static void flexcan_start_chip(can_channel *chan)
     flexcan_regs *flexcan = (flexcan_regs *)info->base;
     
     cyg_uint16 tmp16;
+    
+    info->state = CYGNUM_CAN_STATE_ACTIVE;
     HAL_READ_UINT16(&flexcan->CANMCR, tmp16);    
     HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16 
                  & ~(FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT));
@@ -1223,16 +2331,149 @@ static void flexcan_start_chip(can_channel *chan)
 
 
 //===========================================================================
-//                      SET ACCEPTANCE MASK
+// Stop FlexCAN modul
+//===========================================================================
+static void flexcan_stop_chip(can_channel *chan)
+{
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16    tmp16;
+    
+    info->state = CYGNUM_CAN_STATE_STOPPED;
+    HAL_READ_UINT16(&flexcan->CANMCR, tmp16);    
+    HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16 | FLEXCAN_MCR_HALT);
+}
+
+
+//===========================================================================
+// Set FlexCAN modul into standby mode
+// If the flag selfwake is active then the FlexCAN modul will be set into
+// standby mode with selwake. This means the FlexCAN modul will leave
+// standby as soon as a message box will receive a message
+//===========================================================================
+static void flexcan_enter_standby(can_channel *chan, bool selfwake)
+{
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16    tmp16;
+    cyg_uint8     tmp8;
+    cyg_uint8     i;
+    
+    //
+    // The CPU should disable all interrupts in the FlexCAN before entering low-power
+    // stop mode. Otherwise it may be interrupted while in STOP mode upon a non
+    // wake-up condition; If desired, the WAKEMASK bit should be set to enable the
+    // WAKEINT.
+    //
+    HAL_READ_UINT8(&flexcan->CANCTRL0, tmp8);
+    HAL_WRITE_UINT8(&flexcan->CANCTRL0, tmp8 & ~(FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));
+    
+    //
+    // We disable all message box interrupts. The WAKE DSR will reenable it later
+    // after processing the WAKE event. This ensures that the wake event will be the
+    // first event if a message arrives
+    //
+    HAL_WRITE_UINT16(&flexcan->IMASK, 0); 
+    
+    HAL_READ_UINT16(&flexcan->CANMCR, tmp16);  
+    
+    tmp16 |= FLEXCAN_MCR_STOP;
+    
+    //
+    // if we should go to standby then we activate the SELWAKE bit so that a received
+    // frame will bring us back to live
+    //
+    if (selfwake)
+    {
+        tmp16 |= FLEXCAN_MCR_SELFWAKE;
+    }
+      
+    HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16);
+    
+    //
+    // we have to poll the STOPACK bit in order to determine if chip
+    // has entered stop mode. We poll 10 times - se we spent a maximum
+    // of 2 ms here
+    //
+    for (i = 0; i < 10; ++i)
+    {
+        HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
+        
+        if (tmp16 & FLEXCAN_MCR_STOPACK)
+        {
+            info->state = CYGNUM_CAN_STATE_STANDBY;
+            break;
+        }
+        HAL_DELAY_US(200);
+    }
+    
+    //
+    // if we are not in low power stop mode then we have to reenable interrupts
+    //
+    if (10 == i)
+    {
+        HAL_READ_UINT8(&flexcan->CANCTRL0, tmp8);
+        HAL_WRITE_UINT8(&flexcan->CANCTRL0, tmp8 | (FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));
+    }
+    else
+    {
+        //
+        // if we go into standby then we activate the wake interrupt so we will receive
+        // a wake interrupt if we leave standby and can reenable interrups
+        //
+        if (selfwake)
+        {
+            HAL_READ_UINT16(&flexcan->CANMCR, tmp16);  
+            HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16 | FLEXCAN_MCR_WAKEMSK);  
+        }
+    }
+}
+
+
+//===========================================================================
+// Leave standby mode
+//===========================================================================
+static void flexcan_leave_standby(can_channel *chan)
+{
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16    tmp16;
+    cyg_uint8     i;
+    
+    HAL_READ_UINT16(&flexcan->CANMCR, tmp16);  
+    HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16 & ~(FLEXCAN_MCR_STOP | FLEXCAN_MCR_SELFWAKE));
+    
+    //
+    // we have to poll the STOPACK bit in order to determine if chip
+    // has leaved stop mode. We poll 10 times - se we spent a maximum
+    // of 2 ms here
+    //
+    for (i = 0; i < 10; ++i)
+    {
+        HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
+        
+        if (!(tmp16 & FLEXCAN_MCR_STOPACK))
+        {
+            HAL_WRITE_UINT16(&flexcan->IMASK, info->imask_shadow);
+            info->state = CYGNUM_CAN_STATE_ACTIVE;
+            break;    
+        }
+        HAL_DELAY_US(200);
+    } // for (i = 0; i < 10; ++i)
+}
+
+
+//===========================================================================
+// Set acceptance mask for message buffer
 //===========================================================================
-static void flexcan_set_acceptance_mask(cyg_uint16 *rxmask_reg, cyg_uint32 mask, cyg_uint8 ext)
+static void flexcan_set_acceptance_mask(cyg_uint16 *rxmask_reg, cyg_uint32 mask, cyg_can_id_type ext)
 {
     cyg_uint16 id;
     //
     // 32 bit access to RXMASK filters is broken so we use  16 Bit
     // access here
     //
-    if (ext != 0)
+    if (CYGNUM_CAN_ID_EXT == ext)
     {
         id  = ((mask >> 13) & 0xFFE0);       // set mask bits 18 - 28
         id |= ((mask >> 15) & 0x7);          // set mask bits 15 -17
@@ -1241,7 +2482,7 @@ static void flexcan_set_acceptance_mask(cyg_uint16 *rxmask_reg, cyg_uint32 mask,
         id = (mask << 1) & 0xFFFE;
         HAL_WRITE_UINT16(&rxmask_reg[1], id);
     }
-    else
+    else // (CYGNUM_CAN_ID_STD == ext)
     {
         id = ((mask << 5) & 0xFFE0); 
         HAL_WRITE_UINT16(&rxmask_reg[0], id);
@@ -1253,7 +2494,7 @@ static void flexcan_set_acceptance_mask(cyg_uint16 *rxmask_reg, cyg_uint32 mask,
 
 
 //===========================================================================
-//                 CONFIGURE MESSAGE BOX FOR TRANSMISSION
+// Configure message box for transmission
 //===========================================================================
 static bool flexcan_cfg_mbox_tx(flexcan_mbox     *pmbox,
                                 cyg_can_message  *pmsg,
@@ -1263,7 +2504,7 @@ static bool flexcan_cfg_mbox_tx(flexcan_mbox     *pmbox,
   
     HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_TXCODE_NOT_READY); 
     
-    if (pmsg->ext != 0)
+    if (CYGNUM_CAN_ID_EXT == pmsg->ext)
     { 
         id  = ((pmsg->id >> 13) & 0xFFE0);   // setup id bits 18 - 28
         id |= (MBOX_CFG_IDE | MBOX_CFG_SSR); // set SSR and IDE bit to 1
@@ -1295,8 +2536,9 @@ static bool flexcan_cfg_mbox_tx(flexcan_mbox     *pmbox,
     //
     // Now copy data bytes into buffer and start transmission
     //
-    HAL_WRITE_UINT8_VECTOR(&pmbox->data, pmsg->data, pmsg->dlc, 1); 
+    HAL_WRITE_UINT8_VECTOR(&pmbox->data, pmsg->data.bytes, pmsg->dlc, 1); 
     
+   
     if (rtr)
     {
         HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_TXCODE_RESPONSE | pmsg->dlc);
@@ -1312,41 +2554,44 @@ static bool flexcan_cfg_mbox_tx(flexcan_mbox     *pmbox,
 
 
 //===========================================================================
-//              CONFIGURE MESSAGE BOX FOR RECEPTION OF FRAMES
+// Configure message box for reception of a certain CAN identifier
 //===========================================================================
-static void flexcan_cfg_mbox_rx(flexcan_mbox *pmbox,
-                                cyg_uint32    canid,
-                                cyg_uint8     ext)
+static void flexcan_cfg_mbox_rx(flexcan_mbox     *pmbox,
+                                cyg_can_message  *pmsg,
+                                bool              enable)
 {
     cyg_uint16 id;
     
     HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_NOT_ACTIVE); 
     
-    if (ext != 0)
+    if (CYGNUM_CAN_ID_EXT == pmsg->ext)
     { 
-        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  = ((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);    // write ID high
         
-        id = ((canid << 1) & 0xFFFE);
+        id = ((pmsg->id << 1) & 0xFFFE);
         
         HAL_WRITE_UINT16(&pmbox->id_lo, id);// write ID low
     }   
     else
     {
-        id = ((canid << 5) & 0xFFE0);
+        id = ((pmsg->id << 5) & 0xFFE0);
 
         HAL_WRITE_UINT16(&pmbox->id_hi, id);
         HAL_WRITE_UINT16(&pmbox->id_lo, 0);
     }
     
+    if (enable)
+    {
     HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_EMPTY);
+    }
 }
 
 
 //===========================================================================
-//                       READ DATA FROM MESSAGE BOX
+// Read date from a message box
 //==========================================================================
 static void flexcan_read_from_mbox(can_channel  *chan,
                             cyg_uint8            mbox,
@@ -1358,13 +2603,20 @@ static void flexcan_read_from_mbox(can_channel  *chan,
     flexcan_mbox    *pmbox   = &flexcan->mbox[mbox];
     cyg_can_message *pmsg    = &pevent->msg;
     cyg_uint16       id;
-    cyg_uint8        i;
+    bool             enable_mbox = false;
     
+    //
+    // If controlstat was not read, then read it now
+    //
+    if (FLEXCAN_CTRLSTAT_NOT_READ == *ctrlstat)
+    {
     HAL_READ_UINT8(&pmbox->ctrlstat, *ctrlstat); // this read will lock the mbox
+        enable_mbox = true;
+    }
     
     //
     // 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
+    // This condition will be cleared within 20 cycles - we simply do a 20 ยตs
     // delay here, that should be enougth
     //
     if (*ctrlstat & MBOX_RXCODE_BUSY)
@@ -1373,44 +2625,56 @@ static void flexcan_read_from_mbox(can_channel  *chan,
     }
     
     pmsg->dlc = (*ctrlstat & MBOX_CFG_DLC_MASK); // store received data len
-    pmsg->rtr = 0;
     
-    HAL_READ_UINT16(&pmbox->id_hi, id);         // read ID high
+    HAL_READ_UINT16(&pmbox->id_hi, id);          // read ID high
     
     if (id & MBOX_CFG_IDE)
     {
-        pmsg->ext = 1;
+        pmsg->ext = CYGNUM_CAN_ID_EXT;
         pmsg->id  = (id & 0xFFE0) << 13;
+        pmsg->id |= (id & 0x07) << 15;
         
         HAL_READ_UINT16(&pmbox->id_lo, id);
         pmsg->id |= (id & 0xFFFE) >> 1;
+        
+        if (id & MBOX_CFG_RTR_EXT)
+        {
+            pmsg->rtr = CYGNUM_CAN_FRAME_RTR;
+        }
+        else
+        {
+            pmsg->rtr = CYGNUM_CAN_FRAME_DATA;
+        }
     }
     else
     {
-        pmsg->ext = 0;
+        pmsg->ext = CYGNUM_CAN_ID_STD;
         pmsg->id  = (id & 0xFFE0) >> 5;
+        
+        if (id & MBOX_CFG_RTR_STD)
+        {
+            pmsg->rtr = CYGNUM_CAN_FRAME_RTR;
+        }
+        else
+        {
+            pmsg->rtr = CYGNUM_CAN_FRAME_DATA;
+        }
     }
     
     //
     // now finally copy data
     //
-    HAL_READ_UINT8_VECTOR(&pmbox->data, pmsg->data, pmsg->dlc, 1);
+    HAL_READ_UINT8_VECTOR(&pmbox->data, pmsg->data.bytes, 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
     //
+    if (enable_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