You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/07/29 15:11:39 UTC
[incubator-nuttx] 01/02: drivers/ipcc: add Inter Processor Communication driver
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit a9f78a64db9d51614d87821d5159fe95a1cbeb02
Author: Michał Łyszczek <mi...@bofc.pl>
AuthorDate: Tue Jun 28 15:45:41 2022 +0200
drivers/ipcc: add Inter Processor Communication driver
This patch adds upper half driver for IPCC character driver. IPCC
is a Inter Processor Communication Controller.
Driver is still immature and not thoroughly tested, thus
CONFIG_EXPERIMENTAL is required.
Signed-off-by: Michał Łyszczek <mi...@bofc.pl>
---
drivers/Kconfig | 1 +
drivers/Makefile | 1 +
drivers/ipcc/Kconfig | 33 ++++++
drivers/ipcc/Make.defs | 41 +++++++
drivers/ipcc/ipcc_close.c | 94 ++++++++++++++++
drivers/ipcc/ipcc_open.c | 80 ++++++++++++++
drivers/ipcc/ipcc_poll.c | 203 ++++++++++++++++++++++++++++++++++
drivers/ipcc/ipcc_priv.h | 63 +++++++++++
drivers/ipcc/ipcc_read.c | 232 +++++++++++++++++++++++++++++++++++++++
drivers/ipcc/ipcc_register.c | 189 ++++++++++++++++++++++++++++++++
drivers/ipcc/ipcc_unlink.c | 96 ++++++++++++++++
drivers/ipcc/ipcc_write.c | 256 +++++++++++++++++++++++++++++++++++++++++++
include/nuttx/ipcc.h | 204 ++++++++++++++++++++++++++++++++++
13 files changed, 1493 insertions(+)
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 8a9d162ed6..7bf009d10d 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -14,6 +14,7 @@ source "drivers/clk/Kconfig"
source "drivers/i2c/Kconfig"
source "drivers/spi/Kconfig"
source "drivers/i2s/Kconfig"
+source "drivers/ipcc/Kconfig"
source "drivers/timers/Kconfig"
source "drivers/analog/Kconfig"
source "drivers/audio/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index bfe6cf15f8..e2e0218490 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -36,6 +36,7 @@ include math/Make.defs
include motor/Make.defs
include i2c/Make.defs
include i2s/Make.defs
+include ipcc/Make.defs
include input/Make.defs
include ioexpander/Make.defs
include lcd/Make.defs
diff --git a/drivers/ipcc/Kconfig b/drivers/ipcc/Kconfig
new file mode 100644
index 0000000000..1dbd87c330
--- /dev/null
+++ b/drivers/ipcc/Kconfig
@@ -0,0 +1,33 @@
+menuconfig IPCC
+ bool "IPCC (Inter Processor Communication Controller) driver"
+ select MM_CIRCBUF
+ depends on EXPERIMENTAL
+ default n
+ ---help---
+ IPCC driver. Generic driver to communicate between two
+ processors via character device.
+
+comment "IPCC driver requires CONFIG_EXPERIMENTAL"
+ depends on !EXPERIMENTAL
+
+if IPCC
+
+config IPCC_BUFFERED
+ bool "Enable buffering in driver"
+ default y
+ ---help---
+ If enabled, data read and written to/from IPCC will be
+ buffered in driver. This will reduce thread waiting for
+ read and write to complete during busy period, but it
+ will also increase RAM usage.
+
+ Buffer size for tx and rx can be separately defined for
+ each channel during driver registration.
+
+config IPCC_NPOLLWAITERS
+ int "Number of poll threads"
+ default 4
+ ---help---
+ Maximum number of threads that can be waiting for POLL events.
+
+endif # IPCC
diff --git a/drivers/ipcc/Make.defs b/drivers/ipcc/Make.defs
new file mode 100644
index 0000000000..0892b0de3d
--- /dev/null
+++ b/drivers/ipcc/Make.defs
@@ -0,0 +1,41 @@
+############################################################################
+# drivers/ipcc/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership. The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+ifeq ($(CONFIG_IPCC),y)
+
+# Include ipcc driver
+
+CSRCS += ipcc_poll.c
+CSRCS += ipcc_read.c
+CSRCS += ipcc_write.c
+CSRCS += ipcc_register.c
+CSRCS += ipcc_open.c
+CSRCS += ipcc_close.c
+
+ifneq ($(CONFIG_DISABLE_PSEUDOFS_OPERATIONS),y)
+CSRCS += ipcc_unlink.c
+endif
+
+# Include pipe build support
+
+DEPPATH += --dep-path ipcc
+VPATH += :ipcc
+
+endif # $(CONFIG_IPCC),y
diff --git a/drivers/ipcc/ipcc_close.c b/drivers/ipcc/ipcc_close.c
new file mode 100644
index 0000000000..616e4c72fb
--- /dev/null
+++ b/drivers/ipcc/ipcc_close.c
@@ -0,0 +1,94 @@
+/****************************************************************************
+ * drivers/ipcc/ipcc_close.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/ipcc.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/semaphore.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "ipcc_priv.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ipcc_close
+ *
+ * Description:
+ * Closes the driver device. If this is last reference and file has been
+ * unlinked, we will also free resources allocated by ipcc_register()
+ *
+ * Input Parameters:
+ * filep - pointer to a file structure to close.
+ *
+ * Returned Value:
+ * OK on successfull close, or negated errno on failure.
+ *
+ * Assumptions/Limitations:
+ *
+ ****************************************************************************/
+
+int ipcc_close(FAR struct file *filep)
+{
+ FAR struct ipcc_driver_s *priv;
+ int ret;
+
+ /* Get our private data structure */
+
+ DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
+ priv = filep->f_inode->i_private;
+
+ /* Get exclusive access to the IPCC driver state structure */
+
+ if ((ret = nxsem_wait(&priv->exclsem)) < 0)
+ {
+ return ret;
+ }
+
+ /* Decrement the count of open references on the driver */
+
+ DEBUGASSERT(priv->crefs > 0);
+ priv->crefs--;
+
+ if (priv->crefs <= 0 && priv->unlinked)
+ {
+ /* If count ref is zero and file has been unlinked, it
+ * means nobody uses the driver and seems like nobody
+ * wants to use it anymore, so free up resources.
+ */
+
+ ipcc_cleanup(priv);
+ return OK;
+ }
+
+ nxsem_post(&priv->exclsem);
+ return OK;
+}
diff --git a/drivers/ipcc/ipcc_open.c b/drivers/ipcc/ipcc_open.c
new file mode 100644
index 0000000000..38c1b68bcb
--- /dev/null
+++ b/drivers/ipcc/ipcc_open.c
@@ -0,0 +1,80 @@
+/****************************************************************************
+ * drivers/ipcc/ipcc_open.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/ipcc.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "ipcc_priv.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ipcc_open
+ *
+ * Description:
+ * Opens driver for use by userspace applications.
+ *
+ * Input Parameters:
+ * filep - pointer to a file structure to open.
+ *
+ * Returned Value:
+ * OK on successfull open, or negated errno on failure.
+ *
+ * Assumptions/Limitations:
+ *
+ ****************************************************************************/
+
+int ipcc_open(FAR struct file *filep)
+{
+ FAR struct ipcc_driver_s *priv;
+ int ret;
+
+ /* Get our private data structure */
+
+ DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
+ priv = filep->f_inode->i_private;
+
+ /* Get exclusive access to the IPCC driver state structure */
+
+ if ((ret = nxsem_wait(&priv->exclsem)) < 0)
+ {
+ return ret;
+ }
+
+ /* Increment the count of open references on the driver */
+
+ priv->crefs++;
+ DEBUGASSERT(priv->crefs > 0);
+
+ nxsem_post(&priv->exclsem);
+ return OK;
+}
diff --git a/drivers/ipcc/ipcc_poll.c b/drivers/ipcc/ipcc_poll.c
new file mode 100644
index 0000000000..775682e1e8
--- /dev/null
+++ b/drivers/ipcc/ipcc_poll.c
@@ -0,0 +1,203 @@
+/****************************************************************************
+ * drivers/ipcc/ipcc_poll.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/ipcc.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/semaphore.h>
+
+#include <assert.h>
+#include <debug.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "ipcc_priv.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ipcc_poll
+ *
+ * Description:
+ * Sets up or tears down poll for the driver associated with filep pointer
+ *
+ * Input Parameters:
+ * filep - file associated with the driver instance
+ * fds - The structure describing the events to be monitored, OR NULL if
+ * this is a request to stop monitoring events.
+ * setup - true: Setup up the poll; false: Teardown the poll
+ *
+ * Returned Value:
+ * 0: Success; Negated errno on failure
+ *
+ * Assumptions/Limitations:
+ *
+ ****************************************************************************/
+
+int ipcc_poll(FAR struct file *filep, FAR struct pollfd *fds,
+ bool setup)
+{
+ FAR struct ipcc_driver_s *priv;
+ FAR struct pollfd **slot;
+ pollevent_t eventset;
+ int ret;
+ int i;
+
+ /* Get our private data structure */
+
+ DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
+ priv = filep->f_inode->i_private;
+
+ /* Get exclusive access to driver */
+
+ if ((ret = nxsem_wait(&priv->exclsem)) < 0)
+ {
+ /* nxsem_wait() will return on signal, we did not start
+ * any transfer yet, so we can safely return with error
+ */
+
+ return ret;
+ }
+
+ /* Are we setting up the poll? Or tearing it down? */
+
+ if (!setup)
+ {
+ /* We are tearing down the poll */
+
+ slot = (FAR struct pollfd **)fds->priv;
+
+ /* remove all memory of the poll setup */
+
+ *slot = NULL;
+ fds->priv = NULL;
+ nxsem_post(&priv->exclsem);
+ return OK;
+ }
+
+ /* This is a request to set up the poll. Find an available slot
+ * for the poll structure reference
+ */
+
+ for (i = 0; i < CONFIG_IPCC_NPOLLWAITERS; i++)
+ {
+ /* Find an available slot */
+
+ if (!priv->fds[i])
+ {
+ /* Bind the poll structure and this slot */
+
+ priv->fds[i] = fds;
+ fds->priv = &priv->fds[i];
+ break;
+ }
+ }
+
+ if (i >= CONFIG_IPCC_NPOLLWAITERS)
+ {
+ /* No free poll slot found */
+
+ fds->priv = NULL;
+ nxsem_post(&priv->exclsem);
+ return -EBUSY;
+ }
+
+ /* Should immediately notify on any of the requested events? */
+
+ eventset = 0;
+ if (circbuf_used(&priv->ipcc->rxbuf) > 0)
+ {
+ eventset |= (fds->events & POLLIN);
+ }
+
+ if (circbuf_space(&priv->ipcc->txbuf) > 0)
+ {
+ eventset |= (fds->events & POLLOUT);
+ }
+
+ if (eventset)
+ {
+ ipcc_pollnotify(priv, eventset);
+ }
+
+ nxsem_post(&priv->exclsem);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: ipcc_pollnotify
+ *
+ * Description:
+ * Wakes up all sleeping threads waiting for event associated with ipcc
+ * driver.
+ *
+ * Input Parameters:
+ * ipcc - driver instance to check for poll events
+ * eventset - list of events to check for activity
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions/Limitations:
+ * This function may be called from interrupt handler.
+ *
+ ****************************************************************************/
+
+void ipcc_pollnotify(FAR struct ipcc_driver_s *priv, pollevent_t eventset)
+{
+ struct pollfd *fds;
+ int semcount;
+ int i;
+
+ for (i = 0; i < CONFIG_IPCC_NPOLLWAITERS; i++)
+ {
+ if ((fds = priv->fds[i]) == NULL)
+ {
+ /* Slot empty, move to next one */
+
+ continue;
+ }
+
+ if ((fds->revents |= fds->events & eventset) == 0)
+ {
+ /* No event */
+
+ continue;
+ }
+
+ finfo("Report events: %08" PRIx32 "\n", fds->revents);
+
+ nxsem_get_value(fds->sem, &semcount);
+ if (semcount < 1)
+ {
+ nxsem_post(fds->sem);
+ }
+ }
+}
diff --git a/drivers/ipcc/ipcc_priv.h b/drivers/ipcc/ipcc_priv.h
new file mode 100644
index 0000000000..398c6446e5
--- /dev/null
+++ b/drivers/ipcc/ipcc_priv.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+ * drivers/ipcc/ipcc_priv.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/ipcc.h>
+#include <stdio.h>
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* Driver state structure */
+
+struct ipcc_driver_s
+{
+ FAR struct pollfd *fds[CONFIG_IPCC_NPOLLWAITERS];
+ FAR struct ipcc_lower_s *ipcc; /* Lower half driver state */
+ int crefs; /* Count number of open references */
+ int unlinked; /* 1 - driver has been unlinked */
+ sem_t exclsem; /* Mutual exclusion for driver */
+ sem_t rxsem; /* Data ready to read semaphore */
+ sem_t txsem; /* Data ready to send semaphore */
+};
+
+/****************************************************************************
+ * Public Functions Prototypes
+ ****************************************************************************/
+
+int ipcc_open(FAR struct file *filep);
+int ipcc_close(FAR struct file *filep);
+int ipcc_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+ssize_t ipcc_read(FAR struct file *filep, FAR char *buffer, size_t buflen);
+ssize_t ipcc_write(FAR struct file *filep, FAR const char *buffer,
+ size_t buflen);
+int ipcc_poll(FAR struct file *filep, FAR struct pollfd *fds,
+ bool setup);
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+int ipcc_unlink(FAR struct inode *inode);
+#endif
+
+void ipcc_pollnotify(FAR struct ipcc_driver_s *ipcc, pollevent_t eventset);
+void ipcc_cleanup(FAR struct ipcc_driver_s *priv);
diff --git a/drivers/ipcc/ipcc_read.c b/drivers/ipcc/ipcc_read.c
new file mode 100644
index 0000000000..733575f147
--- /dev/null
+++ b/drivers/ipcc/ipcc_read.c
@@ -0,0 +1,232 @@
+/****************************************************************************
+ * drivers/ipcc/ipcc_read.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/ipcc.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/semaphore.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "ipcc_priv.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ipcc_rxfree_notify
+ *
+ * Description:
+ * Notifies all blocked threads or those waiting in poll/select that
+ * there is data on buffer to perform reading.
+ *
+ * Input Parameters:
+ * ipcc - pointer to driver instance
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions/Limitations:
+ * This function can be called from interrupt handler from lower half.
+ *
+ ****************************************************************************/
+
+void ipcc_rxfree_notify(FAR struct ipcc_driver_s *priv)
+{
+ int semval;
+
+ if (priv == NULL)
+ {
+ /* priv can be NULL when ipcc lower half is initialized but
+ * upper half has not yet been initialized, and rx interrupt
+ * has been received. In such case we don't wake any reader,
+ * because since ipcc is not yet initialized there cannot be
+ * any readers yet. We can safely return here, first read()
+ * to this ipcc channel will immediately read data.
+ */
+
+ return;
+ }
+
+ if ((nxsem_get_value(&priv->rxsem, &semval) == 0) && semval > 0)
+ {
+ /* Notify all poll/select waiters that they can read from the driver.
+ * Do it only when there are no already blocked readers to avoid
+ * situation where thread that is polling gets notified only to
+ * be blocked in read() because another thread have read from
+ * buffer before polling thread could.
+ */
+
+ ipcc_pollnotify(priv, POLLIN);
+ return;
+ }
+
+ /* Notify all blocked readers that data is available to read */
+
+ do
+ {
+ nxsem_post(&priv->rxsem);
+ }
+ while (nxsem_get_value(&priv->rxsem, &semval) == 0 && semval <= 0);
+}
+
+/****************************************************************************
+ * Name: ipcc_read
+ *
+ * Description:
+ * Reads data from the IPCC lower driver. Will block if no data is
+ * available, unless O_NONBLOCK flag is set.
+ *
+ * Input Parameters:
+ * filep - file on vfs associated with the driver
+ * buffer - buffer where read data should be copied to
+ * buflen - size of the buffer... buffer
+ *
+ * Returned Value:
+ * Will return number of bytes read or negated errno
+ *
+ * Assumptions/Limitations:
+ *
+ ****************************************************************************/
+
+ssize_t ipcc_read(FAR struct file *filep, FAR char *buffer,
+ size_t buflen)
+{
+ FAR struct ipcc_driver_s *priv;
+ ssize_t nread;
+ int ret;
+
+ /* Get our private data structure */
+
+ DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
+ priv = filep->f_inode->i_private;
+
+ /* Get exclusive access to driver */
+
+ if ((ret = nxsem_wait(&priv->exclsem)))
+ {
+ /* nxsem_wait() will return on signal, we did not start
+ * any transfer yet, so we can safely return with error
+ */
+
+ return ret;
+ }
+
+ for (; ; )
+ {
+#ifdef CONFIG_IPCC_BUFFERED
+ /* Data is buffered in interrupt handler, so we simply
+ * have to return buffers content to the user
+ */
+
+ if ((nread = circbuf_read(&priv->ipcc->rxbuf, buffer, buflen)) > 0)
+ {
+ /* got some data */
+
+ if (priv->ipcc->overflow)
+ {
+ /* We tried to buffer data in previous interrupt, but
+ * it failed due to rxbuf being full. Now that we took
+ * some data from buffer, we can try to buffer data again
+ */
+
+ priv->ipcc->ops.buffer_data(priv->ipcc, &priv->ipcc->rxbuf);
+
+ if ((size_t)nread < buflen)
+ {
+ /* There is still some space left on buffer, and
+ * we just added new data to buffer, get more data
+ * for the user
+ */
+
+ nread += circbuf_read(&priv->ipcc->rxbuf, buffer + nread,
+ buflen - nread);
+ }
+ }
+
+ /* return number of bytes read to the caller */
+
+ nxsem_post(&priv->exclsem);
+ return nread;
+ }
+
+#else /* CONFIG_IPCC_BUFFERED */
+
+ /* Unbuffered read, read data directly from lower driver */
+
+ if ((nread = priv->ipcc->ops.read(&priv->ipcc, buffer, buflen)) != 0)
+ {
+ /* Got some data, return number of bytes read to the caller
+ * --or--
+ * read() returned error in which case return errno value
+ */
+
+ nxsem_post(&priv->exclsem);
+ return nread;
+ }
+#endif /* CONFIG_IPCC_BUFFERED */
+
+ /* no data on the buffer, should we block? */
+
+ if (filep->f_oflags & O_NONBLOCK)
+ {
+ /* No, we should not block, so inform caller that
+ * no data could be read
+ */
+
+ nxsem_post(&priv->exclsem);
+ return -EAGAIN;
+ }
+
+ /* We are in blocking mode, so we have to wait for data to arrive */
+
+ nxsem_post(&priv->exclsem);
+ if ((ret = nxsem_wait(&priv->rxsem)))
+ {
+ /* We were interrupted by signal, but we have not written
+ * any data to caller's buffer, so we return with error
+ */
+
+ return ret;
+ }
+
+ /* Data should now be available, but it's possible that
+ * another thread will read all data from buffer before
+ * we can do it, so we will stay in the loop until we
+ * manage to read something - or interrupt signal occurs
+ *
+ * We have released exclusive lock to driver when we were
+ * waiting for data, so now let's retake it.
+ */
+
+ nxsem_wait(&priv->exclsem);
+ continue;
+ }
+}
diff --git a/drivers/ipcc/ipcc_register.c b/drivers/ipcc/ipcc_register.c
new file mode 100644
index 0000000000..22d0736b88
--- /dev/null
+++ b/drivers/ipcc/ipcc_register.c
@@ -0,0 +1,189 @@
+/****************************************************************************
+ * drivers/ipcc/ipcc_register.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/ipcc.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/mm/circbuf.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "ipcc_priv.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Device naming ************************************************************/
+
+#define DEVNAME_FMT "/dev/ipcc%d"
+#define DEVNAME_FMTLEN (9 + 3 + 1)
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations ipcc_fops =
+{
+#ifdef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+ .unlink = NULL,
+#else /* CONFIG_DISABLE_PSEUDOFS_OPERATIONS */
+ .unlink = ipcc_unlink,
+#endif /* CONFIG_DISABLE_PSEUDOFS_OPERATIONS */
+ .open = ipcc_open,
+ .close = ipcc_close,
+ .poll = ipcc_poll,
+ .read = ipcc_read,
+ .write = ipcc_write,
+ .ioctl = NULL,
+ .seek = NULL
+};
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ipcc_cleanup
+ *
+ * Description:
+ * Cleans up resources allocated by ipcc_register()
+ *
+ * Input Parameters:
+ * priv - ipcc driver instance to clean up
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions/Limitations:
+ * This function should be called only when ipcc_register is run with
+ * success and all resources in driver instance are properly allocated.
+ *
+ ****************************************************************************/
+
+void ipcc_cleanup(FAR struct ipcc_driver_s *priv)
+{
+#ifdef CONFIG_IPCC_BUFFERED
+ circbuf_uninit(&priv->ipcc->rxbuf);
+ circbuf_uninit(&priv->ipcc->txbuf);
+#endif
+ nxsem_destroy(&priv->rxsem);
+ nxsem_destroy(&priv->txsem);
+ priv->ipcc->ops.cleanup(priv->ipcc);
+ nxsem_destroy(&priv->exclsem);
+ kmm_free(priv);
+}
+
+/****************************************************************************
+ * Name: ipcc_register
+ *
+ * Description:
+ * Create and register the IPCC character driver.
+ *
+ * IPCC is a simple character driver that supports inter processor
+ * communication.
+ *
+ * Input Parameters:
+ * ipcc - An instance of the lower half IPCC driver
+ * chan - IPCC channel. This will be used ad IPCC minor number.
+ * IPPC will be registered as /dev/ipccN where N is the minor number.
+ * buflen - Length of tx and rx buffers, 0 for unbuffered communication.
+ *
+ * Returned Value:
+ * OK if the driver was successfully registered, or negated errno on
+ * failure.
+ *
+ * Assumptions/Limitations:
+ * ipcc is already allocated and initialized by architecture code.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IPCC_BUFFERED
+int ipcc_register(FAR struct ipcc_lower_s *ipcc, size_t rxbuflen,
+ size_t txbuflen)
+#else
+int ipcc_register(FAR struct ipcc_lower_s *ipcc)
+#endif
+{
+ FAR struct ipcc_driver_s *priv;
+ char devname[DEVNAME_FMTLEN];
+ int ret;
+
+ /* Allocate a IPCC character device structure */
+
+ if ((priv = kmm_zalloc(sizeof(*priv))) == NULL)
+ {
+ return -ENOMEM;
+ }
+
+ /* Link upper and lower driver together */
+
+ priv->ipcc = ipcc;
+ ipcc->upper = priv;
+
+#ifdef CONFIG_IPCC_BUFFERED
+ /* allocate buffers for reading and writing data to IPCC memory */
+
+ if (rxbuflen)
+ {
+ if ((ret = circbuf_init(&priv->ipcc->rxbuf, NULL, rxbuflen)))
+ {
+ goto error;
+ }
+ }
+
+ if (txbuflen)
+ {
+ if ((ret = circbuf_init(&priv->ipcc->txbuf, NULL, txbuflen)))
+ {
+ goto error;
+ }
+ }
+#endif /* CONFIG_IPCC_BUFFERED */
+
+ /* Create the character device name */
+
+ snprintf(devname, DEVNAME_FMTLEN, DEVNAME_FMT, ipcc->chan);
+ if ((ret = register_driver(devname, &ipcc_fops, 0666, priv)))
+ {
+ goto error;
+ }
+
+ /* nxsem_init can't really fail us if we provide it with valid params */
+
+ nxsem_init(&priv->exclsem, 0, 1);
+ nxsem_init(&priv->rxsem, 0, 0);
+ nxsem_init(&priv->txsem, 0, 1);
+
+ return OK;
+
+error:
+ ipcc_cleanup(priv);
+
+ return ret;
+}
diff --git a/drivers/ipcc/ipcc_unlink.c b/drivers/ipcc/ipcc_unlink.c
new file mode 100644
index 0000000000..0992631755
--- /dev/null
+++ b/drivers/ipcc/ipcc_unlink.c
@@ -0,0 +1,96 @@
+/****************************************************************************
+ * drivers/ipcc/ipcc_unlink.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/ipcc.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/semaphore.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "ipcc_priv.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ipcc_unlink
+ *
+ * Description:
+ * Action to take upon file unlinking. Function will free resources if
+ * noone is using the driver when unlinking occured. If driver is still
+ * in use, it will be marked as unlinked and resource freeing will take
+ * place in ipcc_close() function instead, once last reference is closed.
+ *
+ * Input Parameters:
+ * inode - driver inode that is being unlinked
+ *
+ * Returned Value:
+ * OK on successfull close, or negated errno on failure.
+ *
+ * Assumptions/Limitations:
+ *
+ ****************************************************************************/
+
+int ipcc_unlink(FAR struct inode *inode)
+{
+ FAR struct ipcc_driver_s *priv;
+ int ret;
+
+ /* Get our private data structure */
+
+ DEBUGASSERT(inode);
+ priv = inode->i_private;
+
+ /* Get exclusive access to the IPCC driver state structure */
+
+ if ((ret = nxsem_wait(&priv->exclsem)) < 0)
+ {
+ return ret;
+ }
+
+ /* Is anyone still using the driver? */
+
+ if (priv->crefs <= 0)
+ {
+ /* No, we are free to free resources */
+
+ ipcc_cleanup(priv);
+ return OK;
+ }
+
+ /* Yes, someone is still using the driver, just mark file
+ * as unlinked and free resources in ipcc_close() once last
+ * reference is closed
+ */
+
+ priv->unlinked = true;
+ nxsem_post(&priv->exclsem);
+ return OK;
+}
diff --git a/drivers/ipcc/ipcc_write.c b/drivers/ipcc/ipcc_write.c
new file mode 100644
index 0000000000..bfe420f96d
--- /dev/null
+++ b/drivers/ipcc/ipcc_write.c
@@ -0,0 +1,256 @@
+/****************************************************************************
+ * drivers/ipcc/ipcc_write.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/ipcc.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/semaphore.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "ipcc_priv.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ipcc_txfree_notify
+ *
+ * Description:
+ * Notifies all blocked threads or those waiting in poll/select that
+ * there is place on buffer to perform writing.
+ *
+ * Input Parameters:
+ * ipcc - pointer to driver instance
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions/Limitations:
+ * This function can be called from interrupt handler from lower half.
+ *
+ ****************************************************************************/
+
+void ipcc_txfree_notify(FAR struct ipcc_driver_s *priv)
+{
+ int semval;
+
+ if (priv == NULL)
+ {
+ /* priv can be NULL when ipcc lower half is initialized but
+ * upper half has not yet been initialized, and tx interrupt
+ * has been received. In such case we don't wake any writers,
+ * because since ipcc is not yet initialized there cannot be
+ * any writers yet. We can safely return here, first write()
+ * to this ipcc channel will immediately write data.
+ */
+
+ return;
+ }
+
+ if ((nxsem_get_value(&priv->txsem, &semval) == 0) && semval > 0)
+ {
+ /* Notify all poll/select waiters that they can write to the driver.
+ * Do it only when there are no already blocked writers to avoid
+ * situation where thread that is polling gets notified only to
+ * be blocked in write() because another thread have written to
+ * buffer before polling thread could.
+ */
+
+ ipcc_pollnotify(priv, POLLOUT);
+ return;
+ }
+
+ /* Notify all blocked writers that data is available to write */
+
+ do
+ {
+ nxsem_post(&priv->txsem);
+ }
+ while (nxsem_get_value(&priv->txsem, &semval) == 0 && semval <= 0);
+}
+
+/****************************************************************************
+ * Name: ipcc_write
+ *
+ * Description:
+ * Writes data to IPCC memory so that another CPU can read the contents.
+ * Will block untill whole buffer is copied unless signal is received
+ * or O_NONBLOCK flag is set.
+ *
+ * Input Parameters:
+ * filep - file on vfs associated with the driver
+ * buffer - buffer to copy to IPCC memory
+ * buflen - size of the buffer... buffer
+ *
+ * Returned Value:
+ * Number of successfully written bytes into the IPCC memory or netagted
+ * errno when no data could be written.
+ *
+ * Assumptions/Limitations:
+ *
+ ****************************************************************************/
+
+ssize_t ipcc_write(FAR struct file *filep, FAR const char *buffer,
+ size_t buflen)
+{
+ FAR struct ipcc_driver_s *priv;
+ ssize_t nwritten;
+ int ret;
+
+ /* Get our private data structure */
+
+ DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
+ priv = filep->f_inode->i_private;
+
+ /* Get exclusive access to driver */
+
+ if ((ret = nxsem_wait(&priv->exclsem)))
+ {
+ /* nxsem_wait() will return on signal, we did not start
+ * any transfer yet, so we can safely return with error
+ */
+
+ return ret;
+ }
+
+ for (nwritten = 0; ; )
+ {
+#ifdef CONFIG_IPCC_BUFFERED
+ /* Buffered write, if buffer is empty try to write directly to
+ * IPCC memory, else buffer data in circbuf - it will be written
+ * in interrupt handler when IPCC tx channel is free.
+ */
+
+ if (circbuf_used(&priv->ipcc->txbuf) == 0)
+ {
+ /* Write buffer is empty, we can try and write data directly
+ * to IPCC memory thus omitting copying to buffer.
+ */
+
+ nwritten += priv->ipcc->ops.write(priv->ipcc, buffer + nwritten,
+ buflen - nwritten);
+ if (nwritten == (ssize_t)buflen || nwritten < 0)
+ {
+ /* We've managed to write whole buffer to IPCC memory,
+ * there is nothing else for use to do
+ * --or--
+ * lower half driver returned error during write,
+ *
+ * either way we return with nwritten which will either
+ * be number of bytes written or negated errno.
+ */
+
+ nxsem_post(&priv->exclsem);
+ return nwritten;
+ }
+ }
+
+ /* Either, there is already some data on the txbuffer, which
+ * means IPCC is occupied, or txbuffer is empty, but we could
+ * not write whole buffer to IPCC memory. In either case we
+ * copy what is left in data to buffer.
+ */
+
+ nwritten += circbuf_write(&priv->ipcc->txbuf, buffer + nwritten,
+ (ssize_t)buflen - nwritten);
+
+ /* Notify lower half that new data on circ buffer is available */
+
+ priv->ipcc->ops.write_notify(priv->ipcc);
+
+ if (nwritten == (ssize_t)buflen)
+ {
+ /* All outstanding data has been copied to txbuffer, we're done */
+
+ nxsem_post(&priv->exclsem);
+ return nwritten;
+ }
+
+#else /* CONFIG_IPCC_BUFFERED */
+ /* Unbuffered write, write data directly to lower driver */
+
+ nwritten += priv->ipcc->ops.write(&priv->ipcc, buffer, buflen);
+ if (nwritten == (ssize_t)buflen)
+ {
+ /* We've managed to write whole buffer to IPCC memory,
+ * there is nothing else for use to do
+ * --or--
+ * lower half driver returned error during write,
+ *
+ * either way we return with nwritten which will either
+ * be number of bytes written or negated errno.
+ */
+
+ nxsem_post(&priv->exclsem);
+ return nwritten;
+ }
+
+#endif /* CONFIG_IPCC_BUFFERED */
+
+ /* No space left on buffer, should we block? */
+
+ if (filep->f_oflags & O_NONBLOCK)
+ {
+ /* No, we should not block, return number of bytes written or
+ * -EAGAIN when we did not write anything
+ */
+
+ nxsem_post(&priv->exclsem);
+ return nwritten ? nwritten : -EAGAIN;
+ }
+
+ /* We are in blocking mode, so we have to wait for space
+ * to write data
+ */
+
+ nxsem_post(&priv->exclsem);
+ if ((ret = nxsem_wait(&priv->txsem)))
+ {
+ /* We were interrupted by signal, return error or number
+ * of bytes written
+ */
+
+ return nwritten ? nwritten : -EINTR;
+ }
+
+ /* Space should now be available, but it's possible that
+ * another thread will write data to txbuffer before
+ * we can do it, so we will stay in the loop until we
+ * manage to write whole buffer - or interrupt signal occurs.
+ *
+ * We have released exclusive lock to driver when we were
+ * waiting for data, so now let's retake it.
+ */
+
+ nxsem_wait(&priv->exclsem);
+ continue;
+ }
+}
diff --git a/include/nuttx/ipcc.h b/include/nuttx/ipcc.h
new file mode 100644
index 0000000000..863513e3c9
--- /dev/null
+++ b/include/nuttx/ipcc.h
@@ -0,0 +1,204 @@
+/****************************************************************************
+ * include/nuttx/ipcc.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_IPCC_H
+#define __INCLUDE_NUTTX_IPCC_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/mm/circbuf.h>
+#include <nuttx/semaphore.h>
+
+#include <poll.h>
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* IPCC is a two-part driver:
+ *
+ * 1) A common upper half driver, that provides the character device
+ * interface for the user
+ * 2) Platform-specific lower half drivers that provide interface
+ * between upper and lower layer. Lower half also contains
+ * common objects like semaphore to inform
+ */
+
+/* This structure defines all of the operations provided by the
+ * architecture specific logic. All fields must be provided with
+ * non-NULL function pointers.
+ */
+
+struct ipcc_lower_s;
+struct ipcc_ops_s
+{
+ /**************************************************************************
+ * Name: read
+ *
+ * Description:
+ * Reads data directly from IPCC mbox, function shall not block.
+ * If no data is available, 0 shall be returned. Partial read
+ * is possible. In that case function can return value less
+ * than buflen.
+ *
+ * Input Parameters:
+ * ipcc - ipcc channel to read data from
+ * buffer - location where data shall be stored
+ * buflen - size of the buffer
+ *
+ * Returned Value:
+ * Number of bytes actually written to buffer.
+ *
+ **************************************************************************/
+
+ CODE ssize_t (*read)(FAR struct ipcc_lower_s *ipcc,
+ FAR char *buffer, size_t buflen);
+
+ /**************************************************************************
+ * Name: write
+ *
+ * Description:
+ * Writes data directly to IPCC mbox, function shall not block.
+ * If IPCC memory is full, or busy or otherwise unavailable for
+ * write, 0 shall be returned. Partial write is possible. In
+ * that case function can return value less then buflen.
+ *
+ * Input Parameters:
+ * ipcc - ipcc channel to write data to
+ * buffer - location to read data from
+ * buflen - number of bytes to write from buffer
+ *
+ * Returned Value:
+ * Number of actually written data to IPCC channel.
+ *
+ **************************************************************************/
+
+ CODE ssize_t (*write)(FAR struct ipcc_lower_s *ipcc,
+ FAR const char *buffer, size_t buflen);
+
+ /**************************************************************************
+ * Name: buffer_data
+ *
+ * Description:
+ * Lower driver shall copy data from IPCC to cirbuf on demand.
+ * It does not have to copy all data (in case rxbuf is full), but
+ * it must keep internal pointer to track uncopied data, and copy
+ * what is left on the next call to this function.
+ *
+ * Input Parameters:
+ * ipcc - channel to buffer data
+ * rxbuf - circural buffer where data should be written to
+ *
+ * Returned Value:
+ * Number of bytes that were successfully written to rxbuf.
+ *
+ **************************************************************************/
+
+ CODE ssize_t (*buffer_data)(FAR struct ipcc_lower_s *ipcc,
+ FAR struct circbuf_s *rxbuf);
+
+ /**************************************************************************
+ * Name: write_notify
+ *
+ * Description:
+ * Upper half driver notifies lower half driver that new data has been
+ * copied to circ buffer. This can be used by lower half to transfer
+ * data from buffer to IPCC memory.
+ *
+ * Input Parameters:
+ * ipcc - ipcc channel that wrote data.
+ *
+ * Returned Value:
+ * 0 on success, or negated errno otherwise
+ *
+ **************************************************************************/
+
+ CODE ssize_t (*write_notify)(FAR struct ipcc_lower_s *ipcc);
+
+ /**************************************************************************
+ * Name: cleanup
+ *
+ * Description:
+ * Cleans up resources initialized by <arch>_ipcc_init(). If arch code
+ * malloc()ed any memory, this funciton is responsible of freeing it.
+ * After this function is called, ipcc driver will not access lower
+ * half pointer anymore.
+ *
+ * Input Parameters:
+ * ipcc - ipcc channel to cleanup
+ *
+ * Returned Value:
+ * Always OK
+ *
+ **************************************************************************/
+
+ CODE int (*cleanup)(FAR struct ipcc_lower_s *ipcc);
+};
+
+/* This structure defines the interface between upper and lower halves.
+ * Such instance is passed to ipcc_register() function after driver
+ * has been initialized, binding the upper and lower halves into one
+ * driver.
+ */
+
+struct ipcc_lower_s
+{
+ /* Pointer to upper half part of the driver. This should be used only
+ * when calling ipcc_* upper half functions from lower half code.
+ * There should be no need to access upper half driver's fields from
+ * lower half context.
+ */
+
+ FAR struct ipcc_driver_s *upper;
+ struct ipcc_ops_s ops; /* Arch specific functions */
+ int chan; /* IPCC channel */
+
+#ifdef CONFIG_IPCC_BUFFERED
+ struct circbuf_s rxbuf; /* Receive buffer */
+ struct circbuf_s txbuf; /* Transmit buffer */
+
+ /* 1 - not all data could fit into buffer, some unread data is still
+ * in IPCC mbox. State of this variable is maintained by lower half,
+ * upper half only reads it to know when to inform lower driver that
+ * buffer got free.
+ */
+
+ int overflow;
+#endif /* CONFIG_IPCC_BUFFERED */
+};
+
+/****************************************************************************
+ * Public Functions Prototypes
+ ****************************************************************************/
+
+void ipcc_txfree_notify(FAR struct ipcc_driver_s *priv);
+void ipcc_rxfree_notify(FAR struct ipcc_driver_s *priv);
+
+#ifdef CONFIG_IPCC_BUFFERED
+int ipcc_register(FAR struct ipcc_lower_s *ipcc, size_t rxbuflen,
+ size_t txbuflen);
+#else
+int ipcc_register(FAR struct ipcc_lower_s *ipcc);
+#endif
+
+#endif /* __INCLUDE_NUTTX_IPCC_H */