You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/06/02 14:09:22 UTC

[incubator-nuttx] 04/31: PoC S32K1XX FlexCAN sends CAN msgs through SocketCAN

This is an automated email from the ASF dual-hosted git repository.

gnutt pushed a commit to branch SocketCAN
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit d600a3dca452519c129d04f03244dff048970428
Author: Peter van der Perk <pe...@nxp.com>
AuthorDate: Wed Feb 19 11:24:31 2020 +0100

    PoC S32K1XX FlexCAN sends CAN msgs through SocketCAN
---
 arch/arm/src/s32k1xx/Kconfig                       |    4 +
 arch/arm/src/s32k1xx/Make.defs                     |    4 +
 arch/arm/src/s32k1xx/hardware/s32k1xx_flexcan.h    |   57 +-
 arch/arm/src/s32k1xx/s32k1xx_flexcan.c             | 1422 ++++++++++++++++++++
 .../arm/src/s32k1xx/s32k1xx_flexcan.h              |  120 +-
 include/nuttx/can.h                                |  279 ++++
 include/nuttx/net/can.h                            |   88 ++
 include/nuttx/net/net.h                            |    3 +-
 net/can/Make.defs                                  |    6 +
 net/can/can.h                                      |   75 ++
 net/{devif/devif_pktsend.c => can/can_callback.c}  |   70 +-
 net/can/can_poll.c                                 |  107 ++
 net/can/can_send.c                                 |  264 ++++
 net/can/can_sockif.c                               |   81 +-
 net/devif/Make.defs                                |    2 +-
 net/devif/devif.h                                  |    4 +-
 net/devif/devif_pktsend.c                          |    2 +-
 net/devif/devif_poll.c                             |   49 +
 net/local/local_sendpacket.c                       |    1 +
 net/netdev/netdev_register.c                       |   12 +
 20 files changed, 2487 insertions(+), 163 deletions(-)

diff --git a/arch/arm/src/s32k1xx/Kconfig b/arch/arm/src/s32k1xx/Kconfig
index 63e0cd9..68f9bb6 100644
--- a/arch/arm/src/s32k1xx/Kconfig
+++ b/arch/arm/src/s32k1xx/Kconfig
@@ -150,6 +150,10 @@ config S32K1XX_ENET
 	default n
 	depends on S32K1XX_HAVE_ENET
 
+config S32K1XX_FLEXCAN
+	bool "FLEXCAN"
+	default n
+
 menuconfig S32K1XX_LPI2C0
 	bool "LPI2C0"
 	default n
diff --git a/arch/arm/src/s32k1xx/Make.defs b/arch/arm/src/s32k1xx/Make.defs
index a06fa86..940dc05 100644
--- a/arch/arm/src/s32k1xx/Make.defs
+++ b/arch/arm/src/s32k1xx/Make.defs
@@ -87,6 +87,10 @@ ifeq ($(CONFIG_S32K1XX_ENET),y)
 CHIP_CSRCS += s32k1xx_enet.c
 endif
 
+ifeq ($(CONFIG_S32K1XX_FLEXCAN),y)
+CHIP_CSRCS += s32k1xx_flexcan.c
+endif
+
 ifeq ($(CONFIG_S32K1XX_RTC),y)
 CHIP_CSRCS += s32k1xx_rtc.c
 endif
diff --git a/arch/arm/src/s32k1xx/hardware/s32k1xx_flexcan.h b/arch/arm/src/s32k1xx/hardware/s32k1xx_flexcan.h
index fa9c36f..03d3d90 100644
--- a/arch/arm/src/s32k1xx/hardware/s32k1xx_flexcan.h
+++ b/arch/arm/src/s32k1xx/hardware/s32k1xx_flexcan.h
@@ -66,6 +66,9 @@
 #define S32K1XX_CAN_CRCR_OFFSET       0x0044  /* CRC Register */
 #define S32K1XX_CAN_RXFGMASK_OFFSET   0x0048  /* Rx FIFO Global Mask Register */
 #define S32K1XX_CAN_RXFIR_OFFSET      0x004c  /* Rx FIFO Information Register */
+#define S32K1XX_CAN_CBT_OFFSET        0x0050  /* CAN Bit Timing register */
+
+#define S32K1XX_CAN_MB_OFFSET         0x0080  /* CAN MB register */
 
 #define S32K1XX_CAN_RXIMR_OFFSET(n)   (0x0880 + ((n) << 2)) /* Rn Individual Mask Registers */
 #  define S32K1XX_CAN_RXIMR0_OFFSET   0x0880  /* R0 Individual Mask Registers */
@@ -162,6 +165,11 @@
 #define S32K1XX_CAN0_CRCR             (S32K1XX_FLEXCAN0_BASE + S32K1XX_CAN_CRCR_OFFSET)
 #define S32K1XX_CAN0_RXFGMASK         (S32K1XX_FLEXCAN0_BASE + S32K1XX_CAN_RXFGMASK_OFFSET)
 #define S32K1XX_CAN0_RXFIR            (S32K1XX_FLEXCAN0_BASE + S32K1XX_CAN_RXFIR_OFFSET)
+#define S32K1XX_CAN0_CBT              (S32K1XX_FLEXCAN0_BASE + S32K1XX_CAN_CBT_OFFSET)
+#define S32K1XX_CAN0_MB               (S32K1XX_FLEXCAN0_BASE + S32K1XX_CAN_MB_OFFSET)
+#define S32K1XX_CAN0_FDCTRL           (S32K1XX_FLEXCAN0_BASE + S32K1XX_CAN_FDCTRL_OFFSET)
+#define S32K1XX_CAN0_FDCBT            (S32K1XX_FLEXCAN0_BASE + S32K1XX_CAN_FDCBT_OFFSET)
+#define S32K1XX_CAN0_FDCRC            (S32K1XX_FLEXCAN0_BASE + S32K1XX_CAN_FDCRC_OFFSET)
 
 #define S32K1XX_CAN0_RXIMR(n)         (S32K1XX_FLEXCAN0_BASE + S32K1XX_CAN_RXIMR_OFFSET(n))
 #  define S32K1XX_CAN0_RXIMR0         (S32K1XX_FLEXCAN0_BASE + S32K1XX_CAN_RXIMR0_OFFSET)
@@ -340,7 +348,8 @@
 #  define CAN_MCR_IDAM_FMTB           (1 << CAN_MCR_IDAM_SHIFT) /* Format B: Two full (or partial) IDs */
 #  define CAN_MCR_IDAM_FMTC           (2 << CAN_MCR_IDAM_SHIFT) /* Format C: Four partial IDs */
 #  define CAN_MCR_IDAM_FMTD           (3 << CAN_MCR_IDAM_SHIFT) /* Format D: All frames rejected */
-                                                /* Bits 10-11: Reserved */
+                                                /* Bit 10: Reserved */
+#define CAN_MCR_FDEN                  (1 << 11) /* Bit 11: CAN FD operation enable */
 #define CAN_MCR_AEN                   (1 << 12) /* Bit 12: Abort Enable */
 #define CAN_MCR_LPRIOEN               (1 << 13) /* Bit 13: Local Priority Enable */
                                                 /* Bits 14-15: Reserved */
@@ -454,7 +463,12 @@
 #define CAN_IFLAG1(n)                 (1 << (n)) /* Bit n: Buffer MBn Interrupt, n=0..4,8..31 */
 
 /* Control 2 Register */
-                                                /* Bits 0-15: Reserved */
+                                                /* Bits 0-10: Reserved */
+#define CAN_CTRL2_EDFLTDIS            (1 << 11) /* Bit 11:  Edge Filter Disable */
+#define CAN_CTRL2_ISOCANFDEN          (1 << 12) /* Bit 12:  ISO CAN FD Enable */
+                                                /* Bit 13:  Reserved */
+#define CAN_CTRL2_PREXCEN             (1 << 14) /* Bit 14:  Protocol Exception Enable */
+#define CAN_CTRL2_TIMER_SRC           (1 << 15) /* Bit 15:  Timer Source */
 #define CAN_CTRL2_EACEN               (1 << 16) /* Bit 16:  Entire Frame Arbitration Field Comparison Enable (Rx) */
 #define CAN_CTRL2_RRS                 (1 << 17) /* Bit 17:  Remote Request Storing */
 #define CAN_CTRL2_MRP                 (1 << 18) /* Bit 18:  Mailboxes Reception Priority */
@@ -506,6 +520,45 @@
 #define CAN_RXFIR_IDHIT_SHIFT         (0)       /* Bits 0-8: Identifier Acceptance Filter Hit Indicator */
 #define CAN_RXFIR_IDHIT_MASK          (0x1ff << CAN_RXFIR_IDHIT_SHIFT)
 
+/* CAN Bit Timing register (CBT) */
+
+/* CBT Bit Fields */
+#define CAN_CBT_EPSEG2(x)             (((uint32_t)(((uint32_t)(x)) << 0))  & 0x1F)
+#define CAN_CBT_EPSEG1(x)             (((uint32_t)(((uint32_t)(x)) << 5))  & 0x3E0)
+#define CAN_CBT_EPROPSEG(x)           (((uint32_t)(((uint32_t)(x)) << 10)) & 0xFC00)
+#define CAN_CBT_ERJW(x)               (((uint32_t)(((uint32_t)(x)) << 16)) & 0x1F0000)
+#define CAN_CBT_EPRESDIV(x)           (((uint32_t)(((uint32_t)(x)) << 21)) & 0x7FE00000)
+#define CAN_CBT_BTF                   (1 << 31) /* Bit 31: Bit Timing Format Enable */
+
+/* CAN MB TX codes */
+#define CAN_TXMB_INACTIVE             0x8       /* MB is not active.*/
+#define CAN_TXMB_ABORT                0x9       /* MB is aborted.*/
+#define CAN_TXMB_DATAORREMOTE         0xC       /* MB is a TX Data Frame(when MB RTR = 0) or */
+                                                /* MB is a TX Remote Request Frame (when MB RTR = 1).*/
+#define CAN_TXMB_TANSWER              0xE       /* MB is a TX Response Request Frame from */
+                                                /* an incoming Remote Request Frame.*/
+#define CAN_TXMB_NOTUSED              0xF       /* Not used.*/
+
+/* CAN FD Control register (FDCTRL) */
+#define CAN_FDCTRL_TDCVAL(x)          (((uint32_t)(((uint32_t)(x)) << 0))  & 0x3F)
+#define CAN_FDCTRL_TDCOFF(x)          (((uint32_t)(((uint32_t)(x)) << 8))  & 0x1F00)
+#define CAN_FDCTRL_TDCEN              (1 << 14) /* Bit 14: TDC fail */
+#define CAN_FDCTRL_TDCEN              (1 << 15) /* Bit 15: TDC enable */
+#define CAN_FDCTRL_MBDSR0(x)          (((uint32_t)(((uint32_t)(x)) << 16)) & 0x30000)
+#define CAN_FDCTRL_FDRATE             (1 << 31) /* Bit 31: FD rate */
+
+/* FDCBT Bit Fields */
+#define CAN_FDCBT_FPSEG2(x)           (((uint32_t)(((uint32_t)(x)) << 0))  & 0x7)
+#define CAN_FDCBT_FPSEG1(x)           (((uint32_t)(((uint32_t)(x)) << 5))  & 0xE0)
+#define CAN_FDCBT_FPROPSEG(x)         (((uint32_t)(((uint32_t)(x)) << 10)) & 0x7C00)
+#define CAN_FDCBT_FRJW(x)             (((uint32_t)(((uint32_t)(x)) << 16)) & 0x70000)
+#define CAN_FDCBT_FPRESDIV(x)         (((uint32_t)(((uint32_t)(x)) << 20)) & 0x3FF00000)
+
+/* FDCRC Bit Fields */
+#define CAN_FDCRC_FD_TXCRC(x)         (((uint32_t)(((uint32_t)(x)) << 0))  & 0x1FFFFF)
+#define CAN_FDCRC_FD_MBCRC(x)         (((uint32_t)(((uint32_t)(x)) << 24)) & 0x7F000000)
+
+
 /* Rn Individual Mask Registers */
 
 #define CAN_RXIMR(n)                  (1 << (n)) /* Bit n: Individual Mask Bits */
diff --git a/arch/arm/src/s32k1xx/s32k1xx_flexcan.c b/arch/arm/src/s32k1xx/s32k1xx_flexcan.c
new file mode 100644
index 0000000..74a21b8
--- /dev/null
+++ b/arch/arm/src/s32k1xx/s32k1xx_flexcan.c
@@ -0,0 +1,1422 @@
+/****************************************************************************
+ * arch/arm/src/s32k1xx/s32k1xx_flexcan.c
+ *
+ *   Copyright (C) 2019 Gregory Nutt. All rights reserved.
+ *   Authors: Gregory Nutt <gn...@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <arpa/inet.h>
+
+#include <nuttx/can.h>
+#include <nuttx/wdog.h>
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/wqueue.h>
+#include <nuttx/signal.h>
+#include <nuttx/net/mii.h>
+#include <nuttx/net/arp.h>
+#include <nuttx/net/phy.h>
+#include <nuttx/net/netdev.h>
+
+#ifdef CONFIG_NET_PKT
+#  include <nuttx/net/pkt.h>
+#endif
+
+#include "up_arch.h"
+#include "chip.h"
+#include "s32k1xx_config.h"
+#include "hardware/s32k1xx_flexcan.h"
+#include "hardware/s32k1xx_pinmux.h"
+#include "s32k1xx_periphclocks.h"
+#include "s32k1xx_pin.h"
+#include "s32k1xx_flexcan.h"
+
+#ifdef CONFIG_S32K1XX_FLEXCAN
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* If processing is not done at the interrupt level, then work queue support
+ * is required.
+ */
+
+#if !defined(CONFIG_SCHED_WORKQUEUE)
+#  error Work queue support is required
+#else
+
+  /* Select work queue.  Always use the LP work queue if available.  If not,
+   * then LPWORK will re-direct to the HP work queue.
+   *
+   * NOTE:  However, the network should NEVER run on the high priority work
+   * queue!  That queue is intended only to service short back end interrupt
+   * processing that never suspends.  Suspending the high priority work queue
+   * may bring the system to its knees!
+   */
+
+#  define ETHWORK LPWORK
+#endif
+
+/* CONFIG_S32K1XX_FLEXCAN_NETHIFS determines the number of physical interfaces
+ * that will be supported.
+ */
+/*
+#if CONFIG_S32K1XX_FLEXCAN_NETHIFS != 1
+#  error "CONFIG_S32K1XX_FLEXCAN_NETHIFS must be one for now"
+#endif
+
+#if CONFIG_S32K1XX_FLEXCAN_NTXBUFFERS < 1
+#  error "Need at least one TX buffer"
+#endif
+
+#if CONFIG_S32K1XX_FLEXCAN_NRXBUFFERS < 1
+#  error "Need at least one RX buffer"
+#endif*/
+
+#define S32K1XX_FLEXCAN_FIRST_TX_MB 10
+
+#define MaskStdID                   0x000007FF;
+#define MaskExtID                   0x1FFFFFFF;
+
+//Fixme nice variables/constants
+#define NumMBinFiFoAndFilters       10 //FIXME
+#define NumTxMesgBuffers            6
+#define HWMaxMB                     16
+#define TXMBMask                    (0b111111 << NumMBinFiFoAndFilters)
+
+#define CAN_FIFO_NE                 (1 << 5)
+#define CAN_FIFO_OV                 (1 << 6)
+#define CAN_FIFO_WARN               (1 << 7)
+
+static int peak_tx_mailbox_index_ = 0;
+
+
+
+
+/* Normally you would clean the cache after writing new values to the DMA
+ * memory so assure that the dirty cache lines are flushed to memory
+ * before the DMA occurs.  And you would invalid the cache after a data is
+ * received via DMA so that you fetch the actual content of the data from
+ * the cache.
+ *
+ * These conditions are not fully supported here.  If the write-throuch
+ * D-Cache is enabled, however, then many of these issues go away:  The
+ * cache clean operation does nothing (because there are not dirty cache
+ * lines) and the cache invalid operation is innocuous (because there are
+ * never dirty cache lines to be lost; valid data will always be reloaded).
+ *
+ * At present, we simply insist that write through cache be enabled.
+ */
+
+#if defined(CONFIG_ARMV7M_DCACHE) && !defined(CONFIG_ARMV7M_DCACHE_WRITETHROUGH)
+#  error Write back D-Cache not yet supported
+#endif
+
+/* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per
+ * second.
+ */
+
+#define S32K1XX_WDDELAY     (1*CLK_TCK)
+
+/* Align assuming that the D-Cache is enabled (probably 32-bytes).
+ *
+ * REVISIT: The size of descriptors and buffers must also be in even units
+ * of the cache line size  That is because the operations to clean and
+ * invalidate the cache will operate on a full 32-byte cache line.  If
+ * CONFIG_FLEXCAN_ENHANCEDBD is selected, then the size of the descriptor is
+ * 32-bytes (and probably already the correct size for the cache line);
+ * otherwise, the size of the descriptors much smaller, only 8 bytes.
+ */
+
+#define FLEXCAN_ALIGN        ARMV7M_DCACHE_LINESIZE
+#define FLEXCAN_ALIGN_MASK   (FLEXCAN_ALIGN - 1)
+#define FLEXCAN_ALIGN_UP(n)  (((n) + FLEXCAN_ALIGN_MASK) & ~FLEXCAN_ALIGN_MASK)
+
+/* TX timeout = 1 minute */
+
+#define S32K1XX_TXTIMEOUT   (60*CLK_TCK)
+#define MII_MAXPOLLS      (0x1ffff)
+#define LINK_WAITUS       (500*1000)
+#define LINK_NLOOPS       (10)
+
+/* Interrupt groups */
+
+#define RX_INTERRUPTS     (FLEXCAN_INT_RXF | FLEXCAN_INT_RXB)
+#define TX_INTERRUPTS      FLEXCAN_INT_TXF
+#define ERROR_INTERRUPTS  (FLEXCAN_INT_UN    | FLEXCAN_INT_RL   | FLEXCAN_INT_LC | \
+                           FLEXCAN_INT_EBERR | FLEXCAN_INT_BABT | FLEXCAN_INT_BABR)
+
+/* The subset of errors that require us to reset the hardware - this list
+ * may need to be revisited if it's found that some error above leads to a
+ * locking up of the Ethernet interface.
+ */
+
+#define CRITICAL_ERROR    (FLEXCAN_INT_UN | FLEXCAN_INT_RL | FLEXCAN_INT_EBERR )
+
+/* This is a helper pointer for accessing the contents of the Ethernet header */
+
+#define BUF ((struct eth_hdr_s *)priv->dev.d_buf)
+
+#define S32K1XX_BUF_SIZE  FLEXCAN_ALIGN_UP(CONFIG_NET_ETH_PKTSIZE)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+
+union TXcsType
+{
+	volatile uint32_t w;
+	struct
+	{
+		volatile uint32_t time_stamp : 16;
+		volatile uint32_t dlc : 4;
+		volatile uint32_t rtr : 1;
+		volatile uint32_t ide : 1;
+		volatile uint32_t srr : 1;
+		volatile uint32_t res : 1;
+		volatile uint32_t code : 4;
+		volatile uint32_t res2 : 4;
+	};
+};
+
+union RXcsType
+{
+	volatile uint32_t cs;
+	struct
+	{
+		volatile uint32_t time_stamp : 16;
+		volatile uint32_t dlc : 4;
+		volatile uint32_t rtr : 1;
+		volatile uint32_t ide : 1;
+		volatile uint32_t srr : 1;
+		volatile uint32_t res : 9;
+	};
+};
+
+union IDType
+{
+	volatile uint32_t w;
+	struct
+	{
+		volatile uint32_t ext : 29;
+		volatile uint32_t resex : 3;
+	};
+	struct
+	{
+		volatile uint32_t res : 18;
+		volatile uint32_t std : 11;
+		volatile uint32_t resstd : 3;
+	};
+};
+
+union DataType
+{
+	volatile uint32_t l;
+	volatile uint32_t h;
+	struct
+	{
+		volatile uint32_t b3 : 8;
+		volatile uint32_t b2 : 8;
+		volatile uint32_t b1 : 8;
+		volatile uint32_t b0 : 8;
+		volatile uint32_t b7 : 8;
+		volatile uint32_t b6 : 8;
+		volatile uint32_t b5 : 8;
+		volatile uint32_t b4 : 8;
+	};
+};
+
+struct MbTx
+{
+	union TXcsType CS;
+	union IDType ID;
+	union DataType data;
+};
+
+struct MbRx
+{
+	union RXcsType CS;
+	union IDType ID;
+	union DataType data;
+};
+
+/* The s32k1xx_driver_s encapsulates all state information for a single
+ * hardware interface
+ */
+
+struct s32k1xx_driver_s
+{
+  bool bifup;                  /* true:ifup false:ifdown */
+  uint8_t txtail;              /* The oldest busy TX descriptor */
+  uint8_t txhead;              /* The next TX descriptor to use */
+  uint8_t rxtail;              /* The next RX descriptor to use */
+  uint8_t phyaddr;             /* Selected PHY address */
+  WDOG_ID txpoll;              /* TX poll timer */
+  WDOG_ID txtimeout;           /* TX timeout timer */
+  struct work_s irqwork;       /* For deferring interrupt work to the work queue */
+  struct work_s pollwork;      /* For deferring poll work to the work queue */
+  struct enet_desc_s *txdesc;  /* A pointer to the list of TX descriptor */
+  struct enet_desc_s *rxdesc;  /* A pointer to the list of RX descriptors */
+
+  /* This holds the information visible to the NuttX network */
+
+  struct net_driver_s dev;     /* Interface understood by the network */
+
+  struct MbRx *rx;
+  struct MbTx *tx;
+
+};
+
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct s32k1xx_driver_s g_flexcan[CONFIG_S32K1XX_ENET_NETHIFS];
+
+static uint8_t g_desc_pool[2000]
+               __attribute__((aligned(ARMV7M_DCACHE_LINESIZE)));
+
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Utility functions */
+
+#ifndef S32K1XX_BUFFERS_SWAP
+#  define s32k1xx_swap32(value) (value)
+#  define s32k1xx_swap16(value) (value)
+#else
+#if 0 /* Use builtins if the compiler supports them */
+static inline uint32_t s32k1xx_swap32(uint32_t value);
+static inline uint16_t s32k1xx_swap16(uint16_t value);
+#else
+#  define s32k1xx_swap32 __builtin_bswap32
+#  define s32k1xx_swap16 __builtin_bswap16
+#endif
+#endif
+
+/* Common TX logic */
+
+static bool s32k1xx_txringfull(FAR struct s32k1xx_driver_s *priv);
+static int  s32k1xx_transmit(FAR struct s32k1xx_driver_s *priv);
+static int  s32k1xx_txpoll(struct net_driver_s *dev);
+
+/* Interrupt handling */
+
+static void s32k1xx_dispatch(FAR struct s32k1xx_driver_s *priv);
+static void s32k1xx_receive(FAR struct s32k1xx_driver_s *priv);
+static void s32k1xx_txdone(FAR struct s32k1xx_driver_s *priv);
+
+static void s32k1xx_flexcan_interrupt_work(FAR void *arg);
+static int  s32k1xx_flexcan_interrupt(int irq, FAR void *context,
+                                   FAR void *arg);
+
+/* Watchdog timer expirations */
+
+static void s32k1xx_txtimeout_work(FAR void *arg);
+static void s32k1xx_txtimeout_expiry(int argc, uint32_t arg, ...);
+
+static void s32k1xx_poll_work(FAR void *arg);
+static void s32k1xx_polltimer_expiry(int argc, uint32_t arg, ...);
+
+/* NuttX callback functions */
+
+static int  s32k1xx_ifup(struct net_driver_s *dev);
+static int  s32k1xx_ifdown(struct net_driver_s *dev);
+
+static void s32k1xx_txavail_work(FAR void *arg);
+static int  s32k1xx_txavail(struct net_driver_s *dev);
+
+#ifdef CONFIG_NET_MCASTGROUP
+static int  s32k1xx_addmac(struct net_driver_s *dev,
+              FAR const uint8_t *mac);
+static int  s32k1xx_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac);
+#endif
+
+#ifdef CONFIG_NETDEV_IOCTL
+static int  s32k1xx_ioctl(struct net_driver_s *dev, int cmd,
+            unsigned long arg);
+#endif
+
+/* Initialization */
+
+static void s32k1xx_initbuffers(struct s32k1xx_driver_s *priv);
+static void s32k1xx_reset(struct s32k1xx_driver_s *priv);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+
+/****************************************************************************
+ * Function: s32k1xx_txringfull
+ *
+ * Description:
+ *   Check if all of the TX descriptors are in use.
+ *
+ * Input Parameters:
+ *   priv  - Reference to the driver state structure
+ *
+ * Returned Value:
+ *   true is the TX ring is full; false if there are free slots at the
+ *   head index.
+ *
+ ****************************************************************************/
+
+static bool s32k1xx_txringfull(FAR struct s32k1xx_driver_s *priv)
+{
+  uint8_t txnext;
+
+  /* Check if there is room in the hardware to hold another outgoing
+   * packet.  The ring is full if incrementing the head pointer would
+   * collide with the tail pointer.
+   */
+
+  txnext = priv->txhead + 1;
+  
+  return priv->txtail == txnext;
+}
+
+/****************************************************************************
+ * Function: s32k1xx_transmit
+ *
+ * Description:
+ *   Start hardware transmission.  Called either from the txdone interrupt
+ *   handling or from watchdog based polling.
+ *
+ * Input Parameters:
+ *   priv  - Reference to the driver state structure
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure
+ *
+ * Assumptions:
+ *   May or may not be called from an interrupt handler.  In either case,
+ *   global interrupts are disabled, either explicitly or indirectly through
+ *   interrupt handling logic.
+ *
+ ****************************************************************************/
+
+
+static int s32k1xx_transmit(FAR struct s32k1xx_driver_s *priv)
+{
+  #warning Missing logic
+
+  struct can_frame *frame = (struct can_frame*)priv->dev.d_buf;
+
+  /*printf("CAN id: %i dlc: %i", frame->can_id, frame->can_dlc);
+
+  for(int i = 0; i < frame->can_dlc; i++){
+	  printf(" %02X", frame->data[i]);
+  }
+  printf("\r\n");*/
+
+  /* Attempt to write frame */
+  uint32_t mbi = 0;
+  if ((getreg32(S32K1XX_CAN0_ESR2) & (CAN_ESR2_IMB | CAN_ESR2_VPS)) == (CAN_ESR2_IMB | CAN_ESR2_VPS))
+  {
+	  mbi = (getreg32(S32K1XX_CAN0_ESR2) & CAN_ESR2_LPTM_MASK) >> CAN_ESR2_LPTM_SHIFT;
+  }
+
+  uint32_t mb_bit = 1 << (NumMBinFiFoAndFilters + mbi);
+
+  while (mbi < NumTxMesgBuffers)
+  {
+
+	  if (priv->tx[mbi].CS.code != CAN_TXMB_DATAORREMOTE)
+	  {
+		  putreg32(mb_bit, S32K1XX_CAN0_IFLAG1);
+		  break;
+	  }
+	  mb_bit <<= 1;
+	  mbi++;
+  }
+
+  if (mbi == NumTxMesgBuffers)
+  {
+	  return 0;       // No transmission for you!
+  }
+
+  peak_tx_mailbox_index_ = (peak_tx_mailbox_index_ > mbi ? peak_tx_mailbox_index_ : mbi );
+
+  union TXcsType cs;
+  cs.code = CAN_TXMB_DATAORREMOTE;
+  struct MbTx* mb = &priv->tx[mbi];
+  mb->CS.code = CAN_TXMB_INACTIVE;
+
+  if (0) //FIXME detect Std or Ext id
+  {
+	  cs.ide = 1;
+	  mb->ID.ext = frame->can_id & MaskExtID;
+  }
+  else
+  {
+	  mb->ID.std = frame->can_id & MaskStdID;
+  }
+
+  //cs.rtr = frame.isRemoteTransmissionRequest();
+
+  cs.dlc = frame->can_dlc;
+  //FIXME endian swap instruction or somekind
+  mb->data.b0 = frame->data[0];
+  mb->data.b1 = frame->data[1];
+  mb->data.b2 = frame->data[2];
+  mb->data.b3 = frame->data[3];
+  mb->data.b4 = frame->data[4];
+  mb->data.b5 = frame->data[5];
+  mb->data.b6 = frame->data[6];
+  mb->data.b7 = frame->data[7];
+
+  /*
+   * Registering the pending transmission so we can track its deadline and loopback it as needed
+   */
+  /*TxItem& txi = pending_tx_[mbi];
+  txi.deadline       = tx_deadline;
+  txi.frame          = frame;
+  txi.loopback       = (flags & uavcan::CanIOFlagLoopback) != 0;
+  txi.abort_on_error = (flags & uavcan::CanIOFlagAbortOnError) != 0;
+  txi.pending        = TxItem::busy;*/
+
+  mb->CS = cs; // Go.
+
+  uint32_t regval;
+  regval = getreg32(S32K1XX_CAN0_IMASK1);
+  regval |= mb_bit;
+  putreg32(regval, S32K1XX_CAN0_IMASK1);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Function: s32k1xx_txpoll
+ *
+ * Description:
+ *   The transmitter is available, check if the network has any outgoing
+ *   packets ready to send.  This is a callback from devif_poll().
+ *   devif_poll() may be called:
+ *
+ *   1. When the preceding TX packet send is complete,
+ *   2. When the preceding TX packet send timesout and the interface is reset
+ *   3. During normal TX polling
+ *
+ * Input Parameters:
+ *   dev  - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure
+ *
+ * Assumptions:
+ *   May or may not be called from an interrupt handler.  In either case,
+ *   global interrupts are disabled, either explicitly or indirectly through
+ *   interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static int s32k1xx_txpoll(struct net_driver_s *dev)
+{
+  #warning Missing logic
+
+  FAR struct s32k1xx_driver_s *priv =
+    (FAR struct s32k1xx_driver_s *)dev->d_private;
+
+  /* If the polling resulted in data that should be sent out on the network,
+   * the field d_len is set to a value > 0.
+   */
+
+  if (priv->dev.d_len > 0)
+    {
+
+      if (!devif_loopback(&priv->dev))
+        {
+          /* Send the packet */
+
+          s32k1xx_transmit(priv);
+          /*priv->dev.d_buf =
+            (uint8_t *)s32k1xx_swap32((uint32_t)priv->txdesc[priv->txhead].data);*/
+
+          /* Check if there is room in the device to hold another packet. If
+           * not, return a non-zero value to terminate the poll.
+           */
+
+          if (s32k1xx_txringfull(priv))
+            {
+              return -EBUSY;
+            }
+        }
+    }
+
+  /* If zero is returned, the polling will continue until all connections
+   * have been examined.
+   */
+
+  return 0;
+}
+
+/****************************************************************************
+ * Function: s32k1xx_dispatch
+ *
+ * Description:
+ *   A new Rx packet was received; dispatch that packet to the network layer
+ *   as necessary.
+ *
+ * Input Parameters:
+ *   priv  - Reference to the driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Global interrupts are disabled by interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static inline void s32k1xx_dispatch(FAR struct s32k1xx_driver_s *priv)
+{
+    
+  #warning Missing logic
+}
+
+/****************************************************************************
+ * Function: s32k1xx_receive
+ *
+ * Description:
+ *   An interrupt was received indicating the availability of a new RX packet
+ *
+ * Input Parameters:
+ *   priv  - Reference to the driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Global interrupts are disabled by interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static void s32k1xx_receive(FAR struct s32k1xx_driver_s *priv)
+{
+  #warning Missing logic
+	printf("FLEXCAN: receive\r\n");
+}
+
+/****************************************************************************
+ * Function: s32k1xx_txdone
+ *
+ * Description:
+ *   An interrupt was received indicating that the last TX packet(s) is done
+ *
+ * Input Parameters:
+ *   priv  - Reference to the driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Global interrupts are disabled by the watchdog logic.
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+static void s32k1xx_txdone(FAR struct s32k1xx_driver_s *priv)
+{
+  #warning Missing logic
+
+  uint32_t tx_iflags;
+  tx_iflags = getreg32(S32K1XX_CAN0_IFLAG1) & TXMBMask;
+
+  //FIXME process aborts
+
+  /* Process TX completions */
+
+  uint32_t mb_bit = 1 << NumMBinFiFoAndFilters;
+  for(uint32_t mbi = 0; tx_iflags && mbi < NumTxMesgBuffers; mbi++)
+  {
+      if (tx_iflags & mb_bit)
+      {
+    	  putreg32(mb_bit, S32K1XX_CAN0_IFLAG1);
+          tx_iflags &= ~mb_bit;
+          const bool txok = priv->tx[mbi].CS.code != CAN_TXMB_ABORT;
+          //handleTxMailboxInterrupt(mbi, txok, utc_usec);
+      }
+      mb_bit <<= 1;
+  }
+}
+
+/****************************************************************************
+ * Function: s32k1xx_flexcan_interrupt_work
+ *
+ * Description:
+ *   Perform interrupt related work from the worker thread
+ *
+ * Input Parameters:
+ *   arg - The argument passed when work_queue() was called.
+ *
+ * Returned Value:
+ *   OK on success
+ *
+ * Assumptions:
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+static void s32k1xx_flexcan_interrupt_work(FAR void *arg)
+{
+  #warning Missing logic
+}
+
+/****************************************************************************
+ * Function: s32k1xx_flexcan_interrupt
+ *
+ * Description:
+ *   Three interrupt sources will vector this this function:
+ *   1. Ethernet MAC transmit interrupt handler
+ *   2. Ethernet MAC receive interrupt handler
+ *   3.
+ *
+ * Input Parameters:
+ *   irq     - Number of the IRQ that generated the interrupt
+ *   context - Interrupt register state save info (architecture-specific)
+ *
+ * Returned Value:
+ *   OK on success
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+
+static int s32k1xx_flexcan_interrupt(int irq, FAR void *context, FAR void *arg)
+{
+  #warning Missing logic
+
+	FAR struct s32k1xx_driver_s *priv = &g_flexcan[0];
+	uint32_t FIFO_IFLAG1 = CAN_FIFO_NE | CAN_FIFO_WARN | CAN_FIFO_OV;
+	uint32_t flags;
+	flags  = getreg32(S32K1XX_CAN0_IFLAG1);
+	flags &= FIFO_IFLAG1;
+
+	if(flags)
+	{
+		s32k1xx_receive(priv);
+	}
+
+	flags  = getreg32(S32K1XX_CAN0_IFLAG1);
+	flags &= TXMBMask;
+
+	if(flags)
+	{
+        s32k1xx_txdone(priv);
+	}
+}
+
+/****************************************************************************
+ * Function: s32k1xx_txtimeout_work
+ *
+ * Description:
+ *   Perform TX timeout related work from the worker thread
+ *
+ * Input Parameters:
+ *   arg - The argument passed when work_queue() as called.
+ *
+ * Returned Value:
+ *   OK on success
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static void s32k1xx_txtimeout_work(FAR void *arg)
+{
+  #warning Missing logic
+	  printf("FLEXCAN: tx timeout work\r\n");
+}
+
+/****************************************************************************
+ * Function: s32k1xx_txtimeout_expiry
+ *
+ * Description:
+ *   Our TX watchdog timed out.  Called from the timer interrupt handler.
+ *   The last TX never completed.  Reset the hardware and start again.
+ *
+ * Input Parameters:
+ *   argc - The number of available arguments
+ *   arg  - The first argument
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Global interrupts are disabled by the watchdog logic.
+ *
+ ****************************************************************************/
+
+static void s32k1xx_txtimeout_expiry(int argc, uint32_t arg, ...)
+{
+  #warning Missing logic
+	  printf("FLEXCAN: tx timeout expiry\r\n");
+}
+
+/****************************************************************************
+ * Function: s32k1xx_poll_work
+ *
+ * Description:
+ *   Perform periodic polling from the worker thread
+ *
+ * Input Parameters:
+ *   arg - The argument passed when work_queue() as called.
+ *
+ * Returned Value:
+ *   OK on success
+ *
+ * Assumptions:
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+static void s32k1xx_poll_work(FAR void *arg)
+{
+  #warning Missing logic
+	  //printf("FLEXCAN: poll work\r\n");
+
+	  FAR struct s32k1xx_driver_s *priv = (FAR struct s32k1xx_driver_s *)arg;
+
+	  /* Check if there is there is a transmission in progress.  We cannot
+	   * perform the TX poll if he are unable to accept another packet for
+	   * transmission.
+	   */
+
+	  net_lock();
+	  if (1) //!s32k1xx_txringfull(priv))
+	    {
+	      /* If so, update TCP timing states and poll the network for new XMIT
+	       * data. Hmmm.. might be bug here.  Does this mean if there is a
+	       * transmit in progress, we will missing TCP time state updates?
+	       */
+
+	      devif_timer(&priv->dev, S32K1XX_WDDELAY, s32k1xx_txpoll);
+	    }
+
+	  /* Setup the watchdog poll timer again in any case */
+
+	  wd_start(priv->txpoll, S32K1XX_WDDELAY, s32k1xx_polltimer_expiry,
+	           1, (wdparm_t)priv);
+	  net_unlock();
+
+}
+
+/****************************************************************************
+ * Function: s32k1xx_polltimer_expiry
+ *
+ * Description:
+ *   Periodic timer handler.  Called from the timer interrupt handler.
+ *
+ * Input Parameters:
+ *   argc - The number of available arguments
+ *   arg  - The first argument
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Global interrupts are disabled by the watchdog logic.
+ *
+ ****************************************************************************/
+
+static void s32k1xx_polltimer_expiry(int argc, uint32_t arg, ...)
+{
+  #warning Missing logic
+  FAR struct s32k1xx_driver_s *priv = (FAR struct s32k1xx_driver_s *)arg;
+
+  /* Schedule to perform the poll processing on the worker thread. */
+
+  work_queue(ETHWORK, &priv->pollwork, s32k1xx_poll_work, priv, 0);
+}
+
+static void s32k1xx_setfreeze(uint32_t freeze)
+{
+	uint32_t regval;
+	if(freeze)
+	{
+		/* Enter freeze mode */
+		regval  = getreg32(S32K1XX_CAN0_MCR);
+		regval |= (CAN_MCR_HALT | CAN_MCR_FRZ);
+		putreg32(regval, S32K1XX_CAN0_MCR);
+	}
+	else
+	{
+		/* Exit freeze mode */
+		regval  = getreg32(S32K1XX_CAN0_MCR);
+		regval &= ~(CAN_MCR_HALT | CAN_MCR_FRZ);
+		putreg32(regval, S32K1XX_CAN0_MCR);
+	}
+}
+
+static uint32_t s32k1xx_waitmcr_change(uint32_t mask, uint32_t target_state)
+{
+	const unsigned Timeout = 1000;
+	for (unsigned wait_ack = 0; wait_ack < Timeout; wait_ack++)
+	{
+		const bool state = (getreg32(S32K1XX_CAN0_MCR) & mask) != 0;
+		if (state == target_state)
+		{
+			return true;
+		}
+		up_udelay(10);
+	}
+	return false;
+}
+
+static uint32_t s32k1xx_waitfreezeack_change(uint32_t target_state)
+{
+    return s32k1xx_waitmcr_change(CAN_MCR_FRZACK, target_state);
+}
+
+
+/****************************************************************************
+ * Function: s32k1xx_ifup
+ *
+ * Description:
+ *   NuttX Callback: Bring up the Ethernet interface when an IP address is
+ *   provided
+ *
+ * Input Parameters:
+ *   dev  - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int s32k1xx_ifup(struct net_driver_s *dev)
+{
+  FAR struct s32k1xx_driver_s *priv =
+	(FAR struct s32k1xx_driver_s *)dev->d_private;
+  uint32_t regval;
+
+  #warning Missing logic
+  printf("FLEXCAN: test ifup\r\n");
+
+  /* initialize CAN device */
+  //FIXME we only support a single can device for now
+
+
+  regval  = getreg32(S32K1XX_CAN0_MCR);
+  regval |= CAN_MCR_MDIS;
+  putreg32(regval, S32K1XX_CAN0_MCR);
+
+  /* Set SYS_CLOCK src */
+  regval  = getreg32(S32K1XX_CAN0_CTRL1);
+  regval |= CAN_CTRL1_CLKSRC;
+  putreg32(regval, S32K1XX_CAN0_CTRL1);
+
+  regval  = getreg32(S32K1XX_CAN0_MCR);
+  regval &= ~(CAN_MCR_MDIS);
+  putreg32(regval, S32K1XX_CAN0_MCR);
+
+
+  regval  = getreg32(S32K1XX_CAN0_MCR);
+  regval |= CAN_MCR_RFEN | CAN_MCR_SLFWAK | CAN_MCR_WRNEN | CAN_MCR_SRXDIS
+		  | CAN_MCR_IRMQ | CAN_MCR_AEN |
+		  (((HWMaxMB - 1) << CAN_MCR_MAXMB_SHIFT) & CAN_MCR_MAXMB_MASK);
+  putreg32(regval, S32K1XX_CAN0_MCR);
+
+  regval  = CAN_CTRL2_RRS | CAN_CTRL2_EACEN | CAN_CTRL2_RFFN_16MB; //FIXME TASD
+  putreg32(regval, S32K1XX_CAN0_CTRL2);
+
+  /* Enter freeze mode */
+  s32k1xx_setfreeze(1);
+  if(!s32k1xx_waitfreezeack_change(1))
+  {
+	  printf("FLEXCAN: freeze fail\r\n");
+	  return -1;
+  }
+
+  /*regval  = getreg32(S32K1XX_CAN0_CTRL1);
+  regval |= ((0  << CAN_CTRL1_PRESDIV_SHIFT) & CAN_CTRL1_PRESDIV_MASK)
+		  | ((46 << CAN_CTRL1_ROPSEG_SHIFT) & CAN_CTRL1_ROPSEG_MASK)
+	      | ((18 << CAN_CTRL1_PSEG1_SHIFT) & CAN_CTRL1_PSEG1_MASK)
+		  | ((12 << CAN_CTRL1_PSEG2_SHIFT) & CAN_CTRL1_PSEG2_MASK)
+		  | ((12 << CAN_CTRL1_RJW_SHIFT) & CAN_CTRL1_RJW_MASK)
+		  | CAN_CTRL1_ERRMSK
+		  | CAN_CTRL1_TWRNMSK
+		  | CAN_CTRL1_RWRNMSK;
+
+  putreg32(regval, S32K1XX_CAN0_CTRL1);*/
+
+  /* CAN Bit Timing (CBT) configuration for a nominal phase of 1 Mbit/s
+   * with 80 time quantas,in accordance with Bosch 2012 specification,
+   * sample point at 83.75% */
+  regval  = getreg32(S32K1XX_CAN0_CBT);
+  regval |= CAN_CBT_BTF |     /* Enable extended bit timing configurations for CAN-FD
+                                      for setting up separetely nominal and data phase */
+            CAN_CBT_EPRESDIV(0) |  /* Prescaler divisor factor of 1 */
+            CAN_CBT_EPROPSEG(46) | /* Propagation segment of 47 time quantas */
+            CAN_CBT_EPSEG1(18) |   /* Phase buffer segment 1 of 19 time quantas */
+            CAN_CBT_EPSEG2(12) |   /* Phase buffer segment 2 of 13 time quantas */
+            CAN_CBT_ERJW(12);      /* Resynchronization jump width same as PSEG2 */
+  putreg32(regval, S32K1XX_CAN0_CBT);
+
+#ifdef CAN_FD
+
+  /* Enable CAN FD feature */
+  regval  = getreg32(S32K1XX_CAN0_MCR);
+  regval |= CAN_MCR_FDEN;
+  putreg32(regval, S32K1XX_CAN0_MCR);
+
+  /* CAN-FD Bit Timing (FDCBT) for a data phase of 4 Mbit/s with 20 time quantas,
+                 in accordance with Bosch 2012 specification, sample point at 75% */
+  regval  = getreg32(S32K1XX_CAN0_FDCBT);
+  regval |= CAN_FDCBT_FPRESDIV(0) | /* Prescaler divisor factor of 1 */
+		  CAN_FDCBT_FPROPSEG(7) | /* Propagation semgment of 7 time quantas
+                                                              (only register that doesn't add 1) */
+		  CAN_FDCBT_FPSEG1(6) |   /* Phase buffer segment 1 of 7 time quantas */
+		  CAN_FDCBT_FPSEG2(4) |   /* Phase buffer segment 2 of 5 time quantas */
+		  CAN_FDCBT_FRJW(4);      /* Resynchorinzation jump width same as PSEG2 */
+  putreg32(regval, S32K1XX_CAN0_FDCBT);
+
+  /* Additional CAN-FD configurations */
+  regval  = getreg32(S32K1XX_CAN0_FDCTRL);
+  regval |= CAN_FDCTRL_FDRATE | /* Enable bit rate switch in data phase of frame */
+		  CAN_FDCTRL_TDCEN |  /* Enable transceiver delay compensation */
+		  CAN_FDCTRL_TDCOFF(5) |   /* Setup 5 cycles for data phase sampling delay */
+		  CAN_FDCTRL_MBDSR0(3);    /* Setup 64 bytes per message buffer (7 MB's) */
+  putreg32(regval, S32K1XX_CAN0_FDCTRL);
+
+  regval  = getreg32(S32K1XX_CAN0_CTRL2);
+  regval |= CAN_CTRL2_ISOCANFDEN;
+  putreg32(regval, S32K1XX_CAN0_CTRL2);
+#endif
+
+
+  /* Filtering catchall */
+  putreg32(0, S32K1XX_CAN0_RXFGMASK);
+
+  /* Iniatilize all MB rx and tx */
+  /*for(int i = 0; i < HWMaxMB; i++)
+  {
+	  priv->rx[i].CS.cs = 0x0;
+	  priv->rx[i].ID.w = 0x0;
+	  priv->rx[i].data.l = 0x0;
+	  priv->rx[i].data.h = 0x0;
+  }*/
+
+  //FIXME max mb
+  for(int i = 0; i < HWMaxMB; i++)
+  {
+	  putreg32(0,S32K1XX_CAN0_RXIMR(i));
+  }
+
+  putreg32(0,S32K1XX_CAN0_RXIMR0);
+  putreg32(0,S32K1XX_CAN0_RXIMR1);
+  putreg32(0,S32K1XX_CAN0_RXIMR2);
+  putreg32(0,S32K1XX_CAN0_RXIMR3);
+  putreg32(0,S32K1XX_CAN0_RXIMR4);
+  putreg32(0,S32K1XX_CAN0_RXIMR5);
+  putreg32(0,S32K1XX_CAN0_RXIMR6);
+  putreg32(0,S32K1XX_CAN0_RXIMR7);
+  putreg32(0,S32K1XX_CAN0_RXIMR8);
+  putreg32(0,S32K1XX_CAN0_RXIMR9);
+  putreg32(0,S32K1XX_CAN0_RXIMR10);
+  putreg32(0,S32K1XX_CAN0_RXIMR11);
+  putreg32(0,S32K1XX_CAN0_RXIMR12);
+  putreg32(0,S32K1XX_CAN0_RXIMR13);
+  putreg32(0,S32K1XX_CAN0_RXIMR14);
+  putreg32(0,S32K1XX_CAN0_RXIMR15);
+
+  putreg32(CAN_IFLAG1(1) | TXMBMask, S32K1XX_CAN0_IFLAG1); //FIXME dynamic MXMB
+  putreg32(CAN_IFLAG1(1), S32K1XX_CAN0_IMASK1);
+
+
+  /* Exit freeze mode */
+  s32k1xx_setfreeze(0);
+  if(!s32k1xx_waitfreezeack_change(0))
+  {
+	  printf("FLEXCAN: unfreeze fail\r\n");
+	  return -1;
+  }
+
+
+  /* Set and activate a timer process */
+
+  wd_start(priv->txpoll, S32K1XX_WDDELAY, s32k1xx_polltimer_expiry, 1,
+           (wdparm_t)priv);
+
+  priv->bifup = true;
+
+  priv->dev.d_buf = &g_desc_pool;
+
+  /* Set interrupts */
+  up_enable_irq(S32K1XX_IRQ_CAN0_BUS);
+  up_enable_irq(S32K1XX_IRQ_CAN0_ERROR);
+  up_enable_irq(S32K1XX_IRQ_CAN0_LPRX);
+  up_enable_irq(S32K1XX_IRQ_CAN0_0_15);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Function: s32k1xx_ifdown
+ *
+ * Description:
+ *   NuttX Callback: Stop the interface.
+ *
+ * Input Parameters:
+ *   dev  - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int s32k1xx_ifdown(struct net_driver_s *dev)
+{
+  #warning Missing logic
+  return OK;
+}
+
+/****************************************************************************
+ * Function: s32k1xx_txavail_work
+ *
+ * Description:
+ *   Perform an out-of-cycle poll on the worker thread.
+ *
+ * Input Parameters:
+ *   arg - Reference to the NuttX driver state structure (cast to void*)
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Called on the higher priority worker thread.
+ *
+ ****************************************************************************/
+
+static void s32k1xx_txavail_work(FAR void *arg)
+{
+	  FAR struct s32k1xx_driver_s *priv = (FAR struct s32k1xx_driver_s *)arg;
+
+	  /* Ignore the notification if the interface is not yet up */
+
+	  net_lock();
+	  if (priv->bifup)
+	    {
+	      /* Check if there is room in the hardware to hold another outgoing
+	       * packet.
+	       */
+
+	      if (!s32k1xx_txringfull(priv))
+	        {
+	          /* No, there is space for another transfer.  Poll the network for
+	           * new XMIT data.
+	           */
+
+	          devif_poll(&priv->dev, s32k1xx_txpoll);
+	        }
+	    }
+
+	  net_unlock();
+}
+
+/****************************************************************************
+ * Function: s32k1xx_txavail
+ *
+ * Description:
+ *   Driver callback invoked when new TX data is available.  This is a
+ *   stimulus perform an out-of-cycle poll and, thereby, reduce the TX
+ *   latency.
+ *
+ * Input Parameters:
+ *   dev  - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Called in normal user mode
+ *
+ ****************************************************************************/
+
+static int s32k1xx_txavail(struct net_driver_s *dev)
+{
+  FAR struct s32k1xx_driver_s *priv =
+    (FAR struct s32k1xx_driver_s *)dev->d_private;
+
+  /* Is our single work structure available?  It may not be if there are
+   * pending interrupt actions and we will have to ignore the Tx
+   * availability action.
+   */
+
+  if (work_available(&priv->pollwork))
+    {
+      /* Schedule to serialize the poll on the worker thread. */
+
+      work_queue(ETHWORK, &priv->pollwork, s32k1xx_txavail_work, priv, 0);
+    }
+
+  return OK;
+}
+
+
+/****************************************************************************
+ * Function: s32k1xx_ioctl
+ *
+ * Description:
+ *   PHY ioctl command handler
+ *
+ * Input Parameters:
+ *   dev  - Reference to the NuttX driver state structure
+ *   cmd  - ioctl command
+ *   arg  - Argument accompanying the command
+ *
+ * Returned Value:
+ *   Zero (OK) on success; a negated errno value on failure.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NETDEV_IOCTL
+static int s32k1xx_ioctl(struct net_driver_s *dev, int cmd,
+                         unsigned long arg)
+{
+  int ret;
+
+  switch (cmd)
+    {
+      default:
+        ret = -ENOTTY;
+        break;
+    }
+
+  return ret;
+}
+#endif /* CONFIG_NETDEV_IOCTL */
+
+
+/****************************************************************************
+ * Function: s32k1xx_initbuffers
+ *
+ * Description:
+ *   Initialize FLEXCAN buffers and descriptors
+ *
+ * Input Parameters:
+ *   priv - Reference to the private FLEXCAN driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static void s32k1xx_initbuffers(struct s32k1xx_driver_s *priv)
+{
+  #warning Missing logic
+}
+
+/****************************************************************************
+ * Function: s32k1xx_reset
+ *
+ * Description:
+ *   Put the EMAC in the non-operational, reset state
+ *
+ * Input Parameters:
+ *   priv - Reference to the private FLEXCAN driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static void s32k1xx_reset(struct s32k1xx_driver_s *priv)
+{
+  unsigned int i;
+
+  /* Set the reset bit and clear the enable bit */
+
+  
+  #warning Missing logic
+
+  /* Wait at least 8 clock cycles */
+
+  for (i = 0; i < 10; i++)
+    {
+      asm volatile ("nop");
+    }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: s32k1xx_netinitialize
+ *
+ * Description:
+ *   Initialize the Ethernet controller and driver
+ *
+ * Input Parameters:
+ *   intf - In the case where there are multiple EMACs, this value
+ *          identifies which EMAC is to be initialized.
+ *
+ * Returned Value:
+ *   OK on success; Negated errno on failure.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+int s32k1xx_netinitialize(int intf)
+{
+  struct s32k1xx_driver_s *priv;
+  int ret;
+
+  //FIXME dynamic board config
+  s32k1xx_pinconfig(PIN_CAN0_TX_4);
+  s32k1xx_pinconfig(PIN_CAN0_RX_4);
+
+  priv = &g_flexcan[intf];
+
+  ninfo("initialize\r\n");
+
+  /* Get the interface structure associated with this interface number. */
+
+    #warning Missing logic
+
+
+  /* Attach the flexcan interrupt handler */
+  if (irq_attach(S32K1XX_IRQ_CAN0_BUS, s32k1xx_flexcan_interrupt, NULL))
+    {
+      /* We could not attach the ISR to the interrupt */
+
+      nerr("ERROR: Failed to attach CAN bus IRQ\n");
+      return -EAGAIN;
+    }
+  if (irq_attach(S32K1XX_IRQ_CAN0_ERROR, s32k1xx_flexcan_interrupt, NULL))
+    {
+      /* We could not attach the ISR to the interrupt */
+
+      nerr("ERROR: Failed to attach CAN error IRQ\n");
+      return -EAGAIN;
+    }
+  if (irq_attach(S32K1XX_IRQ_CAN0_LPRX, s32k1xx_flexcan_interrupt, NULL))
+    {
+      /* We could not attach the ISR to the interrupt */
+
+      nerr("ERROR: Failed to attach CAN LPRX IRQ\n");
+      return -EAGAIN;
+    }
+  if (irq_attach(S32K1XX_IRQ_CAN0_0_15, s32k1xx_flexcan_interrupt, NULL))
+    {
+      /* We could not attach the ISR to the interrupt */
+
+      nerr("ERROR: Failed to attach CAN OR'ed Message buffer (0-15) IRQ\n");
+      return -EAGAIN;
+    }
+
+  /* Initialize the driver structure */
+
+  memset(priv, 0, sizeof(struct s32k1xx_driver_s));
+  priv->dev.d_ifup    = s32k1xx_ifup;     /* I/F up (new IP address) callback */
+  priv->dev.d_ifdown  = s32k1xx_ifdown;   /* I/F down callback */
+  priv->dev.d_txavail = s32k1xx_txavail;  /* New TX data callback */
+#ifdef CONFIG_NETDEV_IOCTL
+  priv->dev.d_ioctl   = s32k1xx_ioctl;    /* Support PHY ioctl() calls */
+#endif
+  priv->dev.d_private = (void *)g_flexcan;   /* Used to recover private state from dev */
+
+  /* Create a watchdog for timing polling for and timing of transmissions */
+  priv->txpoll        = wd_create();      /* Create periodic poll timer */
+  priv->txtimeout     = wd_create();      /* Create TX timeout timer */
+  priv->rx            = (struct MbRx *)(S32K1XX_CAN0_MB);
+  priv->tx            = (struct MbTx *)(S32K1XX_CAN0_MB + (sizeof(struct MbRx)
+		                                * S32K1XX_FLEXCAN_FIRST_TX_MB) );
+
+  /* Put the interface in the down state.  This usually amounts to resetting
+   * the device and/or calling s32k1xx_ifdown().
+   */
+
+  ninfo("callbacks done\r\n");
+
+  s32k1xx_ifdown(&priv->dev);
+
+  /* Register the device with the OS so that socket IOCTLs can be performed */
+
+  netdev_register(&priv->dev, NET_LL_CAN);
+
+  UNUSED(ret);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: up_netinitialize
+ *
+ * Description:
+ *   Initialize the first network interface.  If there are more than one
+ *   interface in the chip, then board-specific logic will have to provide
+ *   this function to determine which, if any, Ethernet controllers should
+ *   be initialized.
+ *
+ ****************************************************************************/
+
+//FIXME CONFIG_S32K1XX_FLEXCAN_NETHIFS == 1 && 
+
+#if !defined(CONFIG_NETDEV_LATEINIT)
+void up_netinitialize(void)
+{
+  s32k1xx_netinitialize(0);
+}
+#endif
+
+#endif /* CONFIG_S32K1XX_FLEXCAN */
diff --git a/net/devif/devif_pktsend.c b/arch/arm/src/s32k1xx/s32k1xx_flexcan.h
similarity index 54%
copy from net/devif/devif_pktsend.c
copy to arch/arm/src/s32k1xx/s32k1xx_flexcan.h
index b041b2f..9dfe681 100644
--- a/net/devif/devif_pktsend.c
+++ b/arch/arm/src/s32k1xx/s32k1xx_flexcan.h
@@ -1,7 +1,7 @@
-/****************************************************************************
- * net/devif/devif_pktsend.c
+/************************************************************************************
+ * arch/arm/src/s32k1xx/s32k1xx_flexcan.h
  *
- *   Copyright (C) 2014 Gregory Nutt. All rights reserved.
+ *   Copyright (C) 2018 Gregory Nutt. All rights reserved.
  *   Author: Gregory Nutt <gn...@nuttx.org>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,83 +31,87 @@
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *
- ****************************************************************************/
+ ************************************************************************************/
 
-/****************************************************************************
+#ifndef __ARCH_ARM_SRC_S32K1XX_S32K1XX_FLEXCAN_H
+#define __ARCH_ARM_SRC_S32K1XX_S32K1XX_FLEXCAN_H
+
+/************************************************************************************
  * Included Files
- ****************************************************************************/
+ ************************************************************************************/
 
 #include <nuttx/config.h>
 
-#include <string.h>
-#include <assert.h>
-#include <debug.h>
-
-#include <nuttx/net/netdev.h>
+#include "hardware/s32k1xx_flexcan.h"
 
-#ifdef CONFIG_NET_PKT
+#ifdef CONFIG_S32K1XX_FLEXCAN
 
-/****************************************************************************
+/************************************************************************************
  * Pre-processor Definitions
- ****************************************************************************/
-
-/****************************************************************************
- * Private Type Declarations
- ****************************************************************************/
-
-/****************************************************************************
- * Private Function Prototypes
- ****************************************************************************/
+ ************************************************************************************/
 
-/****************************************************************************
- * Public Constant Data
- ****************************************************************************/
 
-/****************************************************************************
- * Public Data
- ****************************************************************************/
-
-/****************************************************************************
- * Private Constant Data
- ****************************************************************************/
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
 
-/****************************************************************************
- * Private Data
- ****************************************************************************/
+#ifndef __ASSEMBLY__
 
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
 
-/****************************************************************************
- * Name: devif_pkt_send
+/************************************************************************************
+ * Function: up_netinitialize
  *
  * Description:
- *   Called from socket logic in order to send a raw packet in response to
- *   an xmit or poll request from the network interface driver.
+ *   Initialize the first network interface.  If there are more than one
+ *   interface in the chip, then board-specific logic will have to provide
+ *   this function to determine which, if any, Ethernet controllers should
+ *   be initialized.  Also prototyped in up_internal.h.
  *
- *   This is almost identical to calling devif_send() except that the data to
- *   be sent is copied into dev->d_buf (vs. dev->d_appdata), since there is
- *   no header on the data.
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   OK on success; Negated errno on failure.
  *
  * Assumptions:
- *   Called with the network locked.
+ *   Called very early in the initialization sequence.
  *
- ****************************************************************************/
-
-void devif_pkt_send(FAR struct net_driver_s *dev, FAR const void *buf,
-                    unsigned int len)
-{
-  DEBUGASSERT(dev && len > 0 && len < NETDEV_PKTSIZE(dev));
+ ************************************************************************************/
 
-  /* Copy the data into the device packet buffer */
+void up_netinitialize(void);
 
-  memcpy(dev->d_buf, buf, len);
+/************************************************************************************
+ * Function: s32k1xx_phy_boardinitialize
+ *
+ * Description:
+ *   Some boards require specialized initialization of the PHY before it can be
+ *   used.  This may include such things as configuring GPIOs, resetting the PHY,
+ *   etc.  If CONFIG_S32K1XX_FLEXCAN_PHYINIT is defined in the configuration then the
+ *   board specific logic must provide s32k1xx_phyinitialize();  The i.MX RT Ethernet
+ *   driver will call this function one time before it first uses the PHY.
+ *
+ * Input Parameters:
+ *   intf - Always zero for now.
+ *
+ * Returned Value:
+ *   OK on success; Negated errno on failure.
+ *
+ ************************************************************************************/
 
-  /* Set the number of bytes to send */
 
-  dev->d_len    = len;
-  dev->d_sndlen = len;
+#undef EXTERN
+#if defined(__cplusplus)
 }
+#endif
 
-#endif /* CONFIG_NET_PKT */
+#endif /* __ASSEMBLY__ */
+#endif /* CONFIG_S32K1XX_FLEXCAN */
+#endif /* __ARCH_ARM_SRC_S32K1XX_S32K1XX_FLEXCAN_H */
diff --git a/include/nuttx/can.h b/include/nuttx/can.h
new file mode 100644
index 0000000..fd86b74
--- /dev/null
+++ b/include/nuttx/can.h
@@ -0,0 +1,279 @@
+/************************************************************************************
+ * include/nuttx/can/can.h
+ *
+ *   Copyright (C) 2008, 2009, 2011-2012, 2015-2017, 2019 Gregory Nutt. All rights
+ *     reserved.
+ *   Author: Gregory Nutt <gn...@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_CAN_CAN_H
+#define __INCLUDE_NUTTX_CAN_CAN_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#ifdef CONFIG_CAN_TXREADY
+#  include <nuttx/wqueue.h>
+#endif
+
+#ifdef CONFIG_NET_CAN
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+
+/* Ioctl Commands *******************************************************************/
+
+/* Ioctl commands supported by the upper half CAN driver.
+ *
+ * CANIOC_RTR:
+ *   Description:  Send the remote transmission request and wait for the response.
+ *   Argument:     A reference to struct canioc_rtr_s
+ *
+ * Ioctl commands that may or may not be supported by the lower half CAN driver.
+ *
+ * CANIOC_ADD_STDFILTER:
+ *   Description:    Add an address filter for a standard 11 bit address.
+ *   Argument:       A reference to struct canioc_stdfilter_s
+ *   Returned Value: A non-negative filter ID is returned on success.
+ *                   Otherwise -1 (ERROR) is returned with the errno
+ *                   variable set to indicate the nature of the error.
+ *   Dependencies:   None
+ *
+ * CANIOC_ADD_EXTFILTER:
+ *   Description:    Add an address filter for a extended 29 bit address.
+ *   Argument:       A reference to struct canioc_extfilter_s
+ *   Returned Value: A non-negative filter ID is returned on success.
+ *                   Otherwise -1 (ERROR) is returned with the errno
+ *                   variable set to indicate the nature of the error.
+ *   Dependencies:   Requires CONFIG_CAN_EXTID=y
+ *
+ * CANIOC_DEL_STDFILTER:
+ *   Description:    Remove an address filter for a standard 11 bit address.
+ *   Argument:       The filter index previously returned by the
+ *                   CANIOC_ADD_STDFILTER command
+ *   Returned Value: Zero (OK) is returned on success.  Otherwise -1 (ERROR)
+ *                   is returned with the errno variable set to indicate the
+ *                   nature of the error.
+ *   Dependencies:   None
+ *
+ * CANIOC_DEL_EXTFILTER:
+ *   Description:    Remove an address filter for a standard 29 bit address.
+ *   Argument:       The filter index previously returned by the
+ *                   CANIOC_ADD_EXTFILTER command
+ *   Returned Value: Zero (OK) is returned on success.  Otherwise -1 (ERROR)
+ *                   is returned with the errno variable set to indicate the
+ *                   nature of the error.
+ *   Dependencies:   Requires CONFIG_CAN_EXTID=y
+ *
+ * CANIOC_GET_BITTIMING:
+ *   Description:    Return the current bit timing settings
+ *   Argument:       A pointer to a write-able instance of struct
+ *                   canioc_bittiming_s in which current bit timing values
+ *                   will be returned.
+ *   Returned Value: Zero (OK) is returned on success.  Otherwise -1 (ERROR)
+ *                   is returned with the errno variable set to indicate the
+ *                   nature of the error.
+ *   Dependencies:   None
+ *
+ * CANIOC_SET_BITTIMING:
+ *   Description:    Set new current bit timing values
+ *   Argument:       A pointer to a read-able instance of struct
+ *                   canioc_bittiming_s in which the new bit timing values
+ *                   are provided.
+ *   Returned Value: Zero (OK) is returned on success.  Otherwise -1 (ERROR)
+ *                   is returned with the errno variable set to indicate the
+ *                   nature of the error.
+ *   Dependencies:   None
+ *
+ * CANIOC_GET_CONNMODES:
+ *   Description:    Get the current bus connection modes
+ *   Argument:       A pointer to a write-able instance of struct
+ *                   canioc_connmodes_s in which the new bus modes will be returned.
+ *   Returned Value: Zero (OK) is returned on success.  Otherwise -1 (ERROR)
+ *                   is returned with the errno variable set to indicate the
+ *                   nature of the error.
+ *   Dependencies:   None
+ *
+ * CANIOC_SET_CONNMODES:
+ *   Description:    Set new bus connection modes values
+ *   Argument:       A pointer to a read-able instance of struct
+ *                   canioc_connmodes_s in which the new bus modes are provided.
+ *   Returned Value: Zero (OK) is returned on success.  Otherwise -1 (ERROR)
+ *                   is returned with the errno variable set to indicate the
+ *                   nature of the error.
+ *   Dependencies:   None
+ *
+ * CANIOC_BUSOFF_RECOVERY:
+ *   Description:    Initiates the BUS-OFF recovery sequence
+ *   Argument:       None
+ *   Returned Value: Zero (OK) is returned on success.  Otherwise -1 (ERROR)
+ *                   is returned with the errno variable set to indicate the
+ *                   nature of the error.
+ *   Dependencies:   None
+ */
+
+#define CANIOC_RTR                _CANIOC(1)
+#define CANIOC_GET_BITTIMING      _CANIOC(2)
+#define CANIOC_SET_BITTIMING      _CANIOC(3)
+#define CANIOC_ADD_STDFILTER      _CANIOC(4)
+#define CANIOC_ADD_EXTFILTER      _CANIOC(5)
+#define CANIOC_DEL_STDFILTER      _CANIOC(6)
+#define CANIOC_DEL_EXTFILTER      _CANIOC(7)
+#define CANIOC_GET_CONNMODES      _CANIOC(8)
+#define CANIOC_SET_CONNMODES      _CANIOC(9)
+#define CANIOC_BUSOFF_RECOVERY    _CANIOC(10)
+
+#define CAN_FIRST                 0x0001         /* First common command */
+#define CAN_NCMDS                 10             /* Ten common commands */
+
+/* User defined ioctl commands are also supported. These will be forwarded
+ * by the upper-half CAN driver to the lower-half CAN driver via the co_ioctl()
+ * method fo the CAN lower-half interface.  However, the lower-half driver
+ * must reserve a block of commands as follows in order prevent IOCTL
+ * command numbers from overlapping.
+ *
+ * This is generally done as follows.  The first reservation for CAN driver A would
+ * look like:
+ *
+ *   CAN_A_FIRST                 (CAN_FIRST + CAN_NCMDS)     <- First command
+ *   CAN_A_NCMDS                 42                          <- Number of commands
+ *
+ * IOCTL commands for CAN driver A would then be defined in a CAN A header file like:
+ *
+ *   CANIOC_A_CMD1               _CANIOC(CAN_A_FIRST+0)
+ *   CANIOC_A_CMD2               _CANIOC(CAN_A_FIRST+1)
+ *   CANIOC_A_CMD3               _CANIOC(CAN_A_FIRST+2)
+ *   ...
+ *   CANIOC_A_CMD42              _CANIOC(CAN_A_FIRST+41)
+ *
+ * The next reservation would look like:
+ *
+ *   CAN_B_FIRST                 (CAN_A_FIRST + CAN_A_NCMDS) <- Next command
+ *   CAN_B_NCMDS                 77                          <- Number of commands
+ */
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+typedef uint32_t canid_t;
+
+/* CAN payload length and DLC definitions according to ISO 11898-1 */
+#define CAN_MAX_DLC 8
+#define CAN_MAX_DLEN 8
+
+/* CAN FD payload length and DLC definitions according to ISO 11898-7 */
+#define CANFD_MAX_DLC 15
+#define CANFD_MAX_DLEN 64
+
+
+/**
+ * struct can_frame - basic CAN frame structure
+ * @can_id:  CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition
+ * @can_dlc: frame payload length in byte (0 .. 8) aka data length code
+ *           N.B. the DLC field from ISO 11898-1 Chapter 8.4.2.3 has a 1:1
+ *           mapping of the 'data length code' to the real payload length
+ * @__pad:   padding
+ * @__res0:  reserved / padding
+ * @__res1:  reserved / padding
+ * @data:    CAN frame payload (up to 8 byte)
+ */
+struct can_frame {
+	canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
+	uint8_t    can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */
+	uint8_t    __pad;   /* padding */
+	uint8_t    __res0;  /* reserved / padding */
+	uint8_t    __res1;  /* reserved / padding */
+	uint8_t    data[CAN_MAX_DLEN] __attribute__((aligned(8)));
+};
+
+/*
+ * defined bits for canfd_frame.flags
+ *
+ * The use of struct canfd_frame implies the Extended Data Length (EDL) bit to
+ * be set in the CAN frame bitstream on the wire. The EDL bit switch turns
+ * the CAN controllers bitstream processor into the CAN FD mode which creates
+ * two new options within the CAN FD frame specification:
+ *
+ * Bit Rate Switch - to indicate a second bitrate is/was used for the payload
+ * Error State Indicator - represents the error state of the transmitting node
+ *
+ * As the CANFD_ESI bit is internally generated by the transmitting CAN
+ * controller only the CANFD_BRS bit is relevant for real CAN controllers when
+ * building a CAN FD frame for transmission. Setting the CANFD_ESI bit can make
+ * sense for virtual CAN interfaces to test applications with echoed frames.
+ */
+#define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */
+#define CANFD_ESI 0x02 /* error state indicator of the transmitting node */
+
+/**
+ * struct canfd_frame - CAN flexible data rate frame structure
+ * @can_id: CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition
+ * @len:    frame payload length in byte (0 .. CANFD_MAX_DLEN)
+ * @flags:  additional flags for CAN FD
+ * @__res0: reserved / padding
+ * @__res1: reserved / padding
+ * @data:   CAN FD frame payload (up to CANFD_MAX_DLEN byte)
+ */
+struct canfd_frame {
+	canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
+	uint8_t    len;     /* frame payload length in byte */
+	uint8_t    flags;   /* additional flags for CAN FD */
+	uint8_t    __res0;  /* reserved / padding */
+	uint8_t    __res1;  /* reserved / padding */
+	uint8_t    data[CANFD_MAX_DLEN] __attribute__((aligned(8)));
+};
+
+
+/************************************************************************************
+ * Public Function Prototypes
+ ************************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* CONFIG_CAN */
+#endif /* __INCLUDE_NUTTX_CAN_CAN_H */
diff --git a/include/nuttx/net/can.h b/include/nuttx/net/can.h
new file mode 100644
index 0000000..d426c7b
--- /dev/null
+++ b/include/nuttx/net/can.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+ * include/nuttx/net/ethernt.h
+ * Macros and definitions for the Ethernet link layer.
+ *
+ *   Copyright (C) 2007, 2009-2012, 2015 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <gn...@nuttx.org>
+ *
+ * Derived from uIP with has a similar BSD-styple license:
+ *
+ *   Author: Adam Dunkels <ad...@dunkels.com>
+ *   Copyright (c) 2001-2003, Adam Dunkels.
+ *   All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_NET_CAN_H
+#define __INCLUDE_NUTTX_NET_CAN_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/can.h>
+#include <stdint.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define CAN_HDRLEN 4 //FIXME standard id vs extended
+#define NET_CAN_PKTSIZE sizeof(struct canfd_frame) // max size we can send through socket
+//FIXME think about can & canfd support
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_NUTTX_NET_CAN_H */
diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h
index 8218c0c..8c11db7 100644
--- a/include/nuttx/net/net.h
+++ b/include/nuttx/net/net.h
@@ -155,7 +155,8 @@ enum net_lltype_e
   NET_LL_BLUETOOTH,    /* Bluetooth */
   NET_LL_IEEE80211,    /* IEEE 802.11 */
   NET_LL_IEEE802154,   /* IEEE 802.15.4 MAC */
-  NET_LL_PKTRADIO      /* Non-standard packet radio */
+  NET_LL_PKTRADIO,     /* Non-standard packet radio */
+  NET_LL_CAN           /* CAN bus */
 };
 
 /* This defines a bitmap big enough for one bit for each socket option */
diff --git a/net/can/Make.defs b/net/can/Make.defs
index bb9ef9f..f8488c0 100644
--- a/net/can/Make.defs
+++ b/net/can/Make.defs
@@ -22,8 +22,14 @@
 
 ifeq ($(CONFIG_NET_CAN),y)
 
+# Socket layer
+
 SOCK_CSRCS += can_sockif.c
+SOCK_CSRCS += can_send.c
+
 NET_CSRCS += can_conn.c
+NET_CSRCS += can_poll.c
+NET_CSRCS += can_callback.c
 
 # Include can build support
 
diff --git a/net/can/can.h b/net/can/can.h
index 6f41ce9..3fed49b 100644
--- a/net/can/can.h
+++ b/net/can/can.h
@@ -32,6 +32,7 @@
 
 #include <netpacket/can.h>
 #include <nuttx/semaphore.h>
+#include <nuttx/net/netdev.h>
 
 #include "devif/devif.h"
 #include "socket/socket.h"
@@ -39,6 +40,17 @@
 #ifdef CONFIG_NET_CAN
 
 /****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Allocate a new packet socket data callback */
+
+#define can_callback_alloc(dev,conn) \
+  devif_callback_alloc(dev, &conn->list)
+#define can_callback_free(dev,conn,cb) \
+  devif_conn_callback_free(dev, cb, &conn->list)
+
+/****************************************************************************
  * Public Type Definitions
  ****************************************************************************/
 
@@ -57,6 +69,8 @@ struct can_conn_s
 
   FAR struct devif_callback_s *list; /* NetLink callbacks */
 
+  FAR struct net_driver_s *dev;      /* Reference to CAN device */
+
   /* CAN-specific content follows */
 
   uint8_t protocol;                  /* Selected CAN protocol */
@@ -135,6 +149,43 @@ void can_free(FAR struct can_conn_s *conn);
 FAR struct can_conn_s *can_nextconn(FAR struct can_conn_s *conn);
 
 /****************************************************************************
+ * Name: can_callback
+ *
+ * Description:
+ *   Inform the application holding the packet socket of a change in state.
+ *
+ * Returned Value:
+ *   OK if packet has been processed, otherwise ERROR.
+ *
+ * Assumptions:
+ *   This function is called from network logic at with the network locked.
+ *
+ ****************************************************************************/
+
+uint16_t can_callback(FAR struct net_driver_s *dev,
+                      FAR struct can_conn_s *conn, uint16_t flags);
+
+/****************************************************************************
+ * Name: can_poll
+ *
+ * Description:
+ *   Poll a CAN connection structure for availability of TX data
+ *
+ * Input Parameters:
+ *   dev - The device driver structure to use in the send operation
+ *   conn - The CAN "connection" to poll for TX data
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Called from network stack logic with the network stack locked
+ *
+ ****************************************************************************/
+
+void can_poll(FAR struct net_driver_s *dev, FAR struct can_conn_s *conn);
+
+/****************************************************************************
  * Name: can_active()
  *
  * Description:
@@ -145,6 +196,30 @@ FAR struct can_conn_s *can_nextconn(FAR struct can_conn_s *conn);
 
 FAR struct can_conn_s *can_active(FAR struct sockaddr_can *addr);
 
+/****************************************************************************
+ * Name: psock_can_send
+ *
+ * Description:
+ *   The psock_can_send() call may be used only when the packet socket is in
+ *   a connected state (so that the intended recipient is known).
+ *
+ * Input Parameters:
+ *   psock    An instance of the internal socket structure.
+ *   buf      Data to send
+ *   len      Length of data to send
+ *
+ * Returned Value:
+ *   On success, returns the number of characters sent.  On  error,
+ *   a negated errno value is returned.  See send() for the complete list
+ *   of return values.
+ *
+ ****************************************************************************/
+
+struct socket;
+ssize_t psock_can_send(FAR struct socket *psock, FAR const void *buf,
+                       size_t len);
+
+
 #undef EXTERN
 #ifdef __cplusplus
 }
diff --git a/net/devif/devif_pktsend.c b/net/can/can_callback.c
similarity index 53%
copy from net/devif/devif_pktsend.c
copy to net/can/can_callback.c
index b041b2f..2fad951 100644
--- a/net/devif/devif_pktsend.c
+++ b/net/can/can_callback.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * net/devif/devif_pktsend.c
+ * net/pkt/pkt_callback.c
  *
  *   Copyright (C) 2014 Gregory Nutt. All rights reserved.
  *   Author: Gregory Nutt <gn...@nuttx.org>
@@ -38,76 +38,48 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_CAN)
 
-#include <string.h>
-#include <assert.h>
+#include <stdint.h>
 #include <debug.h>
 
+#include <nuttx/net/netconfig.h>
 #include <nuttx/net/netdev.h>
 
-#ifdef CONFIG_NET_PKT
-
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/****************************************************************************
- * Private Type Declarations
- ****************************************************************************/
-
-/****************************************************************************
- * Private Function Prototypes
- ****************************************************************************/
-
-/****************************************************************************
- * Public Constant Data
- ****************************************************************************/
-
-/****************************************************************************
- * Public Data
- ****************************************************************************/
-
-/****************************************************************************
- * Private Constant Data
- ****************************************************************************/
-
-/****************************************************************************
- * Private Data
- ****************************************************************************/
+#include "devif/devif.h"
+#include "can/can.h"
 
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Name: devif_pkt_send
+ * Name: can_callback
  *
  * Description:
- *   Called from socket logic in order to send a raw packet in response to
- *   an xmit or poll request from the network interface driver.
+ *   Inform the application holding the packet socket of a change in state.
  *
- *   This is almost identical to calling devif_send() except that the data to
- *   be sent is copied into dev->d_buf (vs. dev->d_appdata), since there is
- *   no header on the data.
+ * Returned Value:
+ *   OK if packet has been processed, otherwise ERROR.
  *
  * Assumptions:
- *   Called with the network locked.
+ *   This function is called with the network locked.
  *
  ****************************************************************************/
 
-void devif_pkt_send(FAR struct net_driver_s *dev, FAR const void *buf,
-                    unsigned int len)
+uint16_t can_callback(FAR struct net_driver_s *dev,
+                      FAR struct can_conn_s *conn, uint16_t flags)
 {
-  DEBUGASSERT(dev && len > 0 && len < NETDEV_PKTSIZE(dev));
-
-  /* Copy the data into the device packet buffer */
+  /* Some sanity checking */
 
-  memcpy(dev->d_buf, buf, len);
+  if (conn)
+    {
+      /* Perform the callback */
 
-  /* Set the number of bytes to send */
+      flags = devif_conn_event(dev, conn, flags, conn->list);
+    }
 
-  dev->d_len    = len;
-  dev->d_sndlen = len;
+  return flags;
 }
 
-#endif /* CONFIG_NET_PKT */
+#endif /* CONFIG_NET && CONFIG_NET_CAN */
diff --git a/net/can/can_poll.c b/net/can/can_poll.c
new file mode 100644
index 0000000..84aeeab
--- /dev/null
+++ b/net/can/can_poll.c
@@ -0,0 +1,107 @@
+/****************************************************************************
+ * net/pkt/pkt_poll.c
+ * Poll for the availability of packet TX data
+ *
+ *   Copyright (C) 2014 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <gn...@nuttx.org>
+ *
+ * Adapted for NuttX from logic in uIP which also has a BSD-like license:
+ *
+ *   Original author Adam Dunkels <ad...@dunkels.com>
+ *   Copyright () 2001-2003, Adam Dunkels.
+ *   All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_CAN)
+
+#include <debug.h>
+
+#include <nuttx/net/netconfig.h>
+#include <nuttx/net/netdev.h>
+
+#include "devif/devif.h"
+#include "can/can.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: can_poll
+ *
+ * Description:
+ *   Poll a packet "connection" structure for availability of TX data
+ *
+ * Input Parameters:
+ *   dev - The device driver structure to use in the send operation
+ *   conn - The packet "connection" to poll for TX data
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+void can_poll(FAR struct net_driver_s *dev, FAR struct can_conn_s *conn)
+{
+  /* Verify that the packet connection is valid */
+
+  if (conn != NULL)
+    {
+      /* Setup for the application callback */
+
+      dev->d_appdata = &dev->d_buf[NET_LL_HDRLEN(dev)];
+      dev->d_len     = 0;
+      dev->d_sndlen  = 0;
+
+      /* Perform the application callback */
+
+      can_callback(dev, conn, CAN_POLL);
+
+      /* Check if the application has data to send */
+
+      if (dev->d_sndlen > 0)
+        {
+          return;
+        }
+    }
+
+  /* Make sure that d_len is zero meaning that there is nothing to be sent */
+
+  dev->d_len = 0;
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_CAN */
diff --git a/net/can/can_send.c b/net/can/can_send.c
new file mode 100644
index 0000000..6b7a609
--- /dev/null
+++ b/net/can/can_send.c
@@ -0,0 +1,264 @@
+/****************************************************************************
+ * net/can/can_send.c
+ *
+ *   Copyright (C) 2014, 2016-2017 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <gn...@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_CAN)
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <arch/irq.h>
+
+#include <nuttx/semaphore.h>
+#include <nuttx/net/netdev.h>
+#include <nuttx/net/net.h>
+#include <nuttx/net/ip.h>
+
+#include "netdev/netdev.h"
+#include "devif/devif.h"
+#include "socket/socket.h"
+#include "can/can.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure holds the state of the send operation until it can be
+ * operated upon by the event handler.
+ */
+
+struct send_s
+{
+  FAR struct socket      *snd_sock;    /* Points to the parent socket structure */
+  FAR struct devif_callback_s *snd_cb; /* Reference to callback instance */
+  sem_t                   snd_sem;     /* Used to wake up the waiting thread */
+  FAR const uint8_t      *snd_buffer;  /* Points to the buffer of data to send */
+  size_t                  snd_buflen;  /* Number of bytes in the buffer to send */
+  ssize_t                 snd_sent;    /* The number of bytes sent */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: psock_send_eventhandler
+ ****************************************************************************/
+
+static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
+                                        FAR void *pvconn,
+                                        FAR void *pvpriv, uint16_t flags)
+{
+  FAR struct send_s *pstate = (FAR struct send_s *)pvpriv;
+
+  if (pstate)
+    {
+      /* Check if the outgoing packet is available. It may have been claimed
+       * by a send event handler serving a different thread -OR- if the
+       * output buffer currently contains unprocessed incoming data. In
+       * these cases we will just have to wait for the next polling cycle.
+       */
+
+      if (dev->d_sndlen > 0 || (flags & CAN_NEWDATA) != 0)
+        {
+          /* Another thread has beat us sending data or the buffer is busy,
+           * Check for a timeout. If not timed out, wait for the next
+           * polling cycle and check again.
+           */
+
+          /* No timeout. Just wait for the next polling cycle */
+
+          return flags;
+        }
+
+      /* It looks like we are good to send the data */
+
+      else
+        {
+          /* Copy the packet data into the device packet buffer and send it */
+          //FIXME potentialy wrong function do we have a header??
+    	  devif_pkt_send(dev, pstate->snd_buffer, pstate->snd_buflen);
+          pstate->snd_sent = pstate->snd_buflen;
+        }
+
+      /* Don't allow any further call backs. */
+
+      pstate->snd_cb->flags    = 0;
+      pstate->snd_cb->priv     = NULL;
+      pstate->snd_cb->event    = NULL;
+
+      /* Wake up the waiting thread */
+
+      nxsem_post(&pstate->snd_sem);
+    }
+
+  return flags;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: psock_can_send
+ *
+ * Description:
+ *   The psock_can_send() call may be used only when the packet socket is in
+ *   a connected state (so that the intended recipient is known).
+ *
+ * Input Parameters:
+ *   psock    An instance of the internal socket structure.
+ *   buf      Data to send
+ *   len      Length of data to send
+ *
+ * Returned Value:
+ *   On success, returns the number of characters sent.  On  error,
+ *   a negated errno value is retruend.  See send() for the complete list
+ *   of return values.
+ *
+ ****************************************************************************/
+
+ssize_t psock_can_send(FAR struct socket *psock, FAR const void *buf,
+                       size_t len)
+{
+  FAR struct net_driver_s *dev;
+  FAR struct can_conn_s *conn; 
+  struct send_s state;
+  int ret = OK;
+  
+  conn = (FAR struct can_conn_s *)psock->s_conn;
+
+  /* Verify that the sockfd corresponds to valid, allocated socket */
+
+  if (!psock || psock->s_crefs <= 0)
+    {
+      return -EBADF;
+    }
+
+  /* Get the device driver that will service this transfer */
+
+  dev = conn->dev;
+  if (dev == NULL)
+    {
+      return -ENODEV;
+    }
+
+  /* Perform the send operation */
+
+  /* Initialize the state structure. This is done with the network locked
+   * because we don't want anything to happen until we are ready.
+   */
+
+  net_lock();
+  memset(&state, 0, sizeof(struct send_s));
+
+  /* This semaphore is used for signaling and, hence, should not have
+   * priority inheritance enabled.
+   */
+
+  nxsem_init(&state.snd_sem, 0, 0); /* Doesn't really fail */
+  nxsem_setprotocol(&state.snd_sem, SEM_PRIO_NONE);
+
+  state.snd_sock      = psock;          /* Socket descriptor to use */
+  state.snd_buflen    = len;            /* Number of bytes to send */
+  state.snd_buffer    = buf;            /* Buffer to send from */
+
+  if (len > 0)
+    {
+      /* Allocate resource to receive a callback */
+
+      state.snd_cb = can_callback_alloc(dev, conn);
+      if (state.snd_cb)
+        {
+          /* Set up the callback in the connection */
+
+          state.snd_cb->flags = CAN_POLL;
+          state.snd_cb->priv  = (FAR void *)&state;
+          state.snd_cb->event = psock_send_eventhandler;
+
+          /* Notify the device driver that new TX data is available. */
+
+          netdev_txnotify_dev(dev);
+
+          /* Wait for the send to complete or an error to occur.
+           * net_lockedwait will also terminate if a signal is received.
+           */
+
+          ret = net_lockedwait(&state.snd_sem);
+
+          /* Make sure that no further events are processed */
+
+          can_callback_free(dev, conn, state.snd_cb);
+        }
+    }
+
+  nxsem_destroy(&state.snd_sem);
+  net_unlock();
+
+  /* Check for a errors, Errors are signalled by negative errno values
+   * for the send length
+   */
+
+  if (state.snd_sent < 0)
+    {
+      return state.snd_sent;
+    }
+
+  /* If net_lockedwait failed, then we were probably reawakened by a signal.
+   * In this case, net_lockedwait will have returned negated errno
+   * appropriately.
+   */
+
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* Return the number of bytes actually sent */
+
+  return state.snd_sent;
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_CAN */
diff --git a/net/can/can_sockif.c b/net/can/can_sockif.c
index b7e3fe6..1de95d9 100644
--- a/net/can/can_sockif.c
+++ b/net/can/can_sockif.c
@@ -40,6 +40,7 @@
 #include <nuttx/net/net.h>
 
 #include "can/can.h"
+#include "netdev/netdev.h"
 
 #ifdef CONFIG_NET_CAN
 
@@ -61,7 +62,7 @@ static int  can_connect(FAR struct socket *psock,
               FAR const struct sockaddr *addr, socklen_t addrlen);
 static int  can_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
               FAR socklen_t *addrlen, FAR struct socket *newsock);
-static int  can_poll(FAR struct socket *psock, FAR struct pollfd *fds,
+static int  can_poll_local(FAR struct socket *psock, FAR struct pollfd *fds,
               bool setup);
 static ssize_t can_send(FAR struct socket *psock,
               FAR const void *buf, size_t len, int flags);
@@ -88,7 +89,7 @@ const struct sock_intf_s g_can_sockif =
   can_listen,       /* si_listen */
   can_connect,      /* si_connect */
   can_accept,       /* si_accept */
-  can_poll,         /* si_poll */
+  can_poll_local,         /* si_poll */
   can_send,         /* si_send */
   can_sendto,       /* si_sendto */
 #ifdef CONFIG_NET_SENDFILE
@@ -272,7 +273,15 @@ static int can_bind(FAR struct socket *psock,
 
   canaddr         = (FAR struct sockaddr_can *)addr;
   conn            = (FAR struct can_conn_s *)psock->s_conn;
-#warning Missing logic
+
+  /* Bind CAN device to socket */
+
+  //TODO better support for CONFIG_NETDEV_IFINDEX
+  char netdev_name[6];
+
+  sprintf(netdev_name, "can%i", canaddr->can_ifindex);
+
+  conn->dev = netdev_findbyname(&netdev_name);
 
   return OK;
 }
@@ -473,7 +482,7 @@ static int can_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
 }
 
 /****************************************************************************
- * Name: can_poll
+ * Name: can_poll_local
  *
  * Description:
  *   The standard poll() operation redirects operations on socket descriptors
@@ -495,7 +504,7 @@ static int can_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
  *
  ****************************************************************************/
 
-static int can_poll(FAR struct socket *psock, FAR struct pollfd *fds,
+static int can_poll_local(FAR struct socket *psock, FAR struct pollfd *fds,
                         bool setup)
 {
   FAR struct can_conn_s *conn;
@@ -621,36 +630,25 @@ static int can_poll(FAR struct socket *psock, FAR struct pollfd *fds,
 static ssize_t can_send(FAR struct socket *psock, FAR const void *buf,
                             size_t len, int flags)
 {
-  DEBUGASSERT(psock != NULL && psock->s_conn != NULL && buf != NULL);
-
-  /* The socket must be connected in order to use send */
-
-  if (_SS_ISBOUND(psock->s_flags))
-    {
-      FAR struct can_conn_s *conn;
-      struct sockaddr_can canaddr;
-
-      /* Get the underlying connection structure */
+	  ssize_t ret;
 
-      conn               = (FAR struct can_conn_s *)psock->s_conn;
+	  /* Only SOCK_RAW is supported */
 
-      /* Format the address */
-
-      canaddr.can_family = AF_CAN;
-#warning Missing logic
+	  if (psock->s_type == SOCK_RAW)
+	    {
+	      /* Raw packet send */
+	      ret = psock_can_send(psock, buf, len);
+	    }
+	  else
+	    {
+	      /* EDESTADDRREQ.  Signifies that the socket is not connection-mode and
+	       * no peer address is set.
+	       */
 
-      /* Then let sendto() perform the actual send operation */
-
-      return can_sendto(psock, buf, len, flags,
-                            (FAR const struct sockaddr *)&canaddr,
-                            sizeof(struct sockaddr_can));
-    }
-
-  /* EDESTADDRREQ.  Signifies that the socket is not connection-mode and no
-   * peer address is set.
-   */
+	      ret = -EDESTADDRREQ;
+	    }
 
-  return -EDESTADDRREQ;
+	  return ret;
 }
 
 /****************************************************************************
@@ -681,25 +679,8 @@ static ssize_t can_sendto(FAR struct socket *psock, FAR const void *buf,
                               size_t len, int flags,
                               FAR const struct sockaddr *to, socklen_t tolen)
 {
-  FAR struct can_conn_s *conn;
-  int ret;
-
-  DEBUGASSERT(psock != NULL && psock->s_conn != NULL && buf != NULL &&
-              to != NULL && tolen >= sizeof(struct sockaddr_can));
-
-  conn = (FAR struct can_conn_s *)psock->s_conn;
-#warning Missing logic
-
-  switch (conn->protocol)
-    {
-#warning Missing logic
-
-      default:
-       ret = -EOPNOTSUPP;
-       break;
-    }
-
-  return ret;
+   nerr("ERROR: sendto() not supported for raw packet sockets\n");
+   return -EAFNOSUPPORT;
 }
 
 /****************************************************************************
diff --git a/net/devif/Make.defs b/net/devif/Make.defs
index 714a0ce..b2dca4a 100644
--- a/net/devif/Make.defs
+++ b/net/devif/Make.defs
@@ -62,7 +62,7 @@ endif
 
 # Raw packet socket support
 
-ifeq ($(CONFIG_NET_PKT),y)
+ifeq ($(filter y,$(CONFIG_NET_PKT) $(CONFIG_NET_CAN)),)
 NET_CSRCS += devif_pktsend.c
 endif
 
diff --git a/net/devif/devif.h b/net/devif/devif.h
index cbe1a00..c54a68d 100644
--- a/net/devif/devif.h
+++ b/net/devif/devif.h
@@ -168,6 +168,7 @@
 #define BLUETOOTH_NEWDATA  TCP_NEWDATA
 #define IEEE802154_NEWDATA TCP_NEWDATA
 #define PKT_NEWDATA        TCP_NEWDATA
+#define CAN_NEWDATA        TCP_NEWDATA
 #define WPAN_NEWDATA       TCP_NEWDATA
 #define IPFWD_NEWDATA      TCP_NEWDATA
 #define TCP_SNDACK         (1 << 2)
@@ -175,6 +176,7 @@
 #define TCP_POLL           (1 << 4)
 #define UDP_POLL           TCP_POLL
 #define PKT_POLL           TCP_POLL
+#define CAN_POLL           TCP_POLL
 #define BLUETOOTH_POLL     TCP_POLL
 #define IEEE802154_POLL    TCP_POLL
 #define WPAN_POLL          TCP_POLL
@@ -492,7 +494,7 @@ void devif_iob_send(FAR struct net_driver_s *dev, FAR struct iob_s *buf,
  *
  ****************************************************************************/
 
-#ifdef CONFIG_NET_PKT
+#if defined(CONFIG_NET_PKT) || defined(CONFIG_NET_CAN)
 void devif_pkt_send(FAR struct net_driver_s *dev, FAR const void *buf,
                     unsigned int len);
 #endif
diff --git a/net/devif/devif_pktsend.c b/net/devif/devif_pktsend.c
index b041b2f..a5d0515 100644
--- a/net/devif/devif_pktsend.c
+++ b/net/devif/devif_pktsend.c
@@ -45,7 +45,7 @@
 
 #include <nuttx/net/netdev.h>
 
-#ifdef CONFIG_NET_PKT
+#if defined(CONFIG_NET_PKT) || defined(CONFIG_NET_CAN)
 
 /****************************************************************************
  * Pre-processor Definitions
diff --git a/net/devif/devif_poll.c b/net/devif/devif_poll.c
index 7c4fd04..e997a6f 100644
--- a/net/devif/devif_poll.c
+++ b/net/devif/devif_poll.c
@@ -50,6 +50,7 @@
 
 #include "devif/devif.h"
 #include "arp/arp.h"
+#include "can/can.h"
 #include "tcp/tcp.h"
 #include "udp/udp.h"
 #include "pkt/pkt.h"
@@ -233,6 +234,46 @@ static int devif_poll_pkt_connections(FAR struct net_driver_s *dev,
 #endif /* CONFIG_NET_PKT */
 
 /****************************************************************************
+ * Name: devif_poll_pkt_connections
+ *
+ * Description:
+ *   Poll all packet connections for available packets to send.
+ *
+ * Assumptions:
+ *   This function is called from the MAC device driver with the network
+ *   locked.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_CAN
+static int devif_poll_can_connections(FAR struct net_driver_s *dev,
+                                      devif_poll_callback_t callback)
+{
+  FAR struct can_conn_s *can_conn = NULL;
+  int bstop = 0;
+
+  /* Traverse all of the allocated packet connections and perform the poll action */
+
+  while (!bstop && (can_conn = can_nextconn(can_conn)))
+    {
+      /* Perform the packet TX poll */
+
+      can_poll(dev, can_conn);
+
+      /* Perform any necessary conversions on outgoing packets */
+
+      devif_packet_conversion(dev, DEVIF_CAN);
+
+      /* Call back into the driver */
+
+      bstop = callback(dev);
+    }
+
+  return bstop;
+}
+#endif /* CONFIG_NET_PKT */
+
+/****************************************************************************
  * Name: devif_poll_bluetooth_connections
  *
  * Description:
@@ -646,6 +687,14 @@ int devif_poll(FAR struct net_driver_s *dev, devif_poll_callback_t callback)
 
   if (!bstop)
 #endif
+#ifdef CONFIG_NET_CAN
+    {
+      /* Check for pending packet socket transfer */
+      bstop = devif_poll_can_connections(dev, callback);
+    }
+
+  if (!bstop)
+#endif
 #ifdef CONFIG_NET_BLUETOOTH
     {
       /* Check for pending PF_BLUETOOTH socket transfer */
diff --git a/net/local/local_sendpacket.c b/net/local/local_sendpacket.c
index 68dfac6..644dd31 100644
--- a/net/local/local_sendpacket.c
+++ b/net/local/local_sendpacket.c
@@ -47,6 +47,7 @@
 #include <debug.h>
 
 #include <nuttx/fs/fs.h>
+#include "devif/devif.h"
 
 #include "local/local.h"
 
diff --git a/net/netdev/netdev_register.c b/net/netdev/netdev_register.c
index 85483dc..fc4634b 100644
--- a/net/netdev/netdev_register.c
+++ b/net/netdev/netdev_register.c
@@ -37,6 +37,7 @@
 #include <nuttx/net/netdev.h>
 #include <nuttx/net/ethernet.h>
 #include <nuttx/net/bluetooth.h>
+#include <nuttx/net/can.h>
 
 #include "utils/utils.h"
 #include "igmp/igmp.h"
@@ -55,6 +56,7 @@
 #define NETDEV_PAN_FORMAT   "pan%d"
 #define NETDEV_WLAN_FORMAT  "wlan%d"
 #define NETDEV_WPAN_FORMAT  "wpan%d"
+#define NETDEV_CAN_FORMAT   "can%d"
 
 #if defined(CONFIG_DRIVERS_IEEE80211) /* Usually also has CONFIG_NET_ETHERNET */
 #  define NETDEV_DEFAULT_FORMAT NETDEV_WLAN_FORMAT
@@ -66,6 +68,8 @@
 #  define NETDEV_DEFAULT_FORMAT NETDEV_SLIP_FORMAT
 #elif defined(CONFIG_NET_TUN)
 #  define NETDEV_DEFAULT_FORMAT NETDEV_TUN_FORMAT
+#elif defined(CONFIG_NET_CAN)
+#  define NETDEV_DEFAULT_FORMAT NETDEV_CAN_FORMAT
 #else /* if defined(CONFIG_NET_LOOPBACK) */
 #  define NETDEV_DEFAULT_FORMAT NETDEV_LO_FORMAT
 #endif
@@ -276,6 +280,14 @@ int netdev_register(FAR struct net_driver_s *dev, enum net_lltype_e lltype)
             break;
 #endif
 
+#ifdef CONFIG_NET_CAN
+          case NET_LL_CAN:  /* CAN bus */
+            dev->d_llhdrlen = 0;
+            dev->d_pktsize  = NET_CAN_PKTSIZE;
+            devfmt          = NETDEV_CAN_FORMAT;
+            break;
+#endif
+
 #ifdef CONFIG_NET_BLUETOOTH
           case NET_LL_BLUETOOTH:              /* Bluetooth */
             llhdrlen = BLUETOOTH_MAX_HDRLEN;  /* Determined at runtime */