brcm2708: drop support for 3.3 kernel
[openwrt.git] / target / linux / brcm2708 / patches-3.3 / 0005-bcm2708-vchiq-driver.patch
diff --git a/target/linux/brcm2708/patches-3.3/0005-bcm2708-vchiq-driver.patch b/target/linux/brcm2708/patches-3.3/0005-bcm2708-vchiq-driver.patch
deleted file mode 100644 (file)
index 47c6d8e..0000000
+++ /dev/null
@@ -1,16383 +0,0 @@
-From a2e42fbc97cde9e851f5b036f46b8f34a5be6eb9 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Tue, 17 Jan 2012 19:22:19 +0000
-Subject: [PATCH 5/7] bcm2708 vchiq driver
-
-Signed-off-by: popcornmix <popcornmix@gmail.com>
----
- drivers/misc/Kconfig                               |    1 +
- drivers/misc/Makefile                              |    1 +
- drivers/misc/vc04_services/Kconfig                 |    7 +
- drivers/misc/vc04_services/Makefile                |   19 +
- .../misc/vc04_services/interface/vchi/vchi_mh.h    |   19 +
- .../misc/vc04_services/interface/vchiq_arm/vchiq.h |   27 +
- .../vc04_services/interface/vchiq_arm/vchiq_2835.h |   27 +
- .../interface/vchiq_arm/vchiq_2835_arm.c           |  487 ++++
- .../vc04_services/interface/vchiq_arm/vchiq_arm.c  | 1293 ++++++++++
- .../vc04_services/interface/vchiq_arm/vchiq_arm.h  |   38 +
- .../vc04_services/interface/vchiq_arm/vchiq_cfg.h  |   43 +
- .../interface/vchiq_arm/vchiq_connected.c          |  101 +
- .../interface/vchiq_arm/vchiq_connected.h          |   32 +
- .../vc04_services/interface/vchiq_arm/vchiq_core.c | 2604 ++++++++++++++++++++
- .../vc04_services/interface/vchiq_arm/vchiq_core.h |  480 ++++
- .../vc04_services/interface/vchiq_arm/vchiq_if.h   |  148 ++
- .../interface/vchiq_arm/vchiq_ioctl.h              |  105 +
- .../interface/vchiq_arm/vchiq_kern_lib.c           |  297 +++
- .../vc04_services/interface/vchiq_arm/vchiq_lib.c  | 1518 ++++++++++++
- .../interface/vchiq_arm/vchiq_memdrv.h             |   45 +
- .../interface/vchiq_arm/vchiq_pagelist.h           |   43 +
- .../vc04_services/interface/vchiq_arm/vchiq_shim.c |  970 ++++++++
- .../vc04_services/interface/vchiq_arm/vchiq_util.c |   97 +
- .../vc04_services/interface/vchiq_arm/vchiq_util.h |   47 +
- .../interface/vcos/generic/vcos_cmd.c              |  681 +++++
- .../interface/vcos/generic/vcos_common.h           |   76 +
- .../vcos/generic/vcos_generic_blockpool.h          |  260 ++
- .../vcos/generic/vcos_generic_event_flags.c        |  297 +++
- .../vcos/generic/vcos_generic_event_flags.h        |  104 +
- .../vcos/generic/vcos_generic_named_sem.h          |   81 +
- .../vcos/generic/vcos_generic_quickslow_mutex.h    |   75 +
- .../vcos/generic/vcos_generic_reentrant_mtx.h      |   75 +
- .../interface/vcos/generic/vcos_generic_tls.h      |  144 ++
- .../vcos/generic/vcos_joinable_thread_from_plain.h |  202 ++
- .../interface/vcos/generic/vcos_latch_from_sem.h   |   48 +
- .../interface/vcos/generic/vcos_logcat.c           |  549 +++++
- .../interface/vcos/generic/vcos_mem_from_malloc.c  |   73 +
- .../interface/vcos/generic/vcos_mem_from_malloc.h  |   54 +
- .../vcos/generic/vcos_mutexes_are_reentrant.h      |   68 +
- .../interface/vcos/generic/vcos_thread_reaper.h    |   35 +
- .../interface/vcos/linuxkernel/stdint.h            |   17 +
- .../interface/vcos/linuxkernel/vcos_linuxkernel.c  |  616 +++++
- .../vcos/linuxkernel/vcos_linuxkernel_cfg.c        |  332 +++
- .../vcos/linuxkernel/vcos_linuxkernel_misc.c       |  113 +
- .../interface/vcos/linuxkernel/vcos_mod_init.c     |   64 +
- .../interface/vcos/linuxkernel/vcos_platform.h     |  496 ++++
- .../vcos/linuxkernel/vcos_platform_types.h         |   47 +
- .../interface/vcos/linuxkernel/vcos_thread_map.c   |  129 +
- .../interface/vcos/linuxkernel/vcos_thread_map.h   |   39 +
- drivers/misc/vc04_services/interface/vcos/vcos.h   |  201 ++
- .../vc04_services/interface/vcos/vcos_assert.h     |  269 ++
- .../interface/vcos/vcos_atomic_flags.h             |   72 +
- .../vc04_services/interface/vcos/vcos_build_info.h |    5 +
- .../misc/vc04_services/interface/vcos/vcos_cfg.h   |  113 +
- .../misc/vc04_services/interface/vcos/vcos_cmd.h   |   98 +
- .../misc/vc04_services/interface/vcos/vcos_ctype.h |   29 +
- .../misc/vc04_services/interface/vcos/vcos_dlfcn.h |   69 +
- .../misc/vc04_services/interface/vcos/vcos_event.h |   97 +
- .../interface/vcos/vcos_event_flags.h              |   98 +
- .../misc/vc04_services/interface/vcos/vcos_init.h  |   43 +
- .../vc04_services/interface/vcos/vcos_logging.h    |  279 +++
- .../interface/vcos/vcos_lowlevel_thread.h          |  107 +
- .../misc/vc04_services/interface/vcos/vcos_mem.h   |   81 +
- .../vc04_services/interface/vcos/vcos_msgqueue.h   |  157 ++
- .../misc/vc04_services/interface/vcos/vcos_mutex.h |   92 +
- .../misc/vc04_services/interface/vcos/vcos_once.h  |   42 +
- .../vc04_services/interface/vcos/vcos_semaphore.h  |  115 +
- .../vc04_services/interface/vcos/vcos_stdbool.h    |   17 +
- .../vc04_services/interface/vcos/vcos_stdint.h     |  193 ++
- .../vc04_services/interface/vcos/vcos_string.h     |   73 +
- .../vc04_services/interface/vcos/vcos_thread.h     |  259 ++
- .../interface/vcos/vcos_thread_attr.h              |   73 +
- .../misc/vc04_services/interface/vcos/vcos_timer.h |   95 +
- .../misc/vc04_services/interface/vcos/vcos_types.h |  197 ++
- 74 files changed, 15998 insertions(+), 0 deletions(-)
- create mode 100644 drivers/misc/vc04_services/Kconfig
- create mode 100644 drivers/misc/vc04_services/Makefile
- create mode 100644 drivers/misc/vc04_services/interface/vchi/vchi_mh.h
- create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h
- create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h
- create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
- create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c
- create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h
- create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h
- create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c
- create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h
- create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c
- create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h
- create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h
- create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h
- create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c
- create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_lib.c
- create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h
- create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h
- create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c
- create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c
- create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/generic/vcos_cmd.c
- create mode 100644 drivers/misc/vc04_services/interface/vcos/generic/vcos_common.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_blockpool.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_event_flags.c
- create mode 100644 drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_event_flags.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_named_sem.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_quickslow_mutex.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_reentrant_mtx.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_tls.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/generic/vcos_joinable_thread_from_plain.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/generic/vcos_latch_from_sem.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/generic/vcos_logcat.c
- create mode 100644 drivers/misc/vc04_services/interface/vcos/generic/vcos_mem_from_malloc.c
- create mode 100644 drivers/misc/vc04_services/interface/vcos/generic/vcos_mem_from_malloc.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/generic/vcos_mutexes_are_reentrant.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/generic/vcos_thread_reaper.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/linuxkernel/stdint.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel.c
- create mode 100644 drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel_cfg.c
- create mode 100644 drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel_misc.c
- create mode 100644 drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_mod_init.c
- create mode 100644 drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_platform.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_platform_types.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_thread_map.c
- create mode 100644 drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_thread_map.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_assert.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_atomic_flags.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_build_info.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_cfg.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_cmd.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_ctype.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_dlfcn.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_event.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_event_flags.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_init.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_logging.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_lowlevel_thread.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_mem.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_msgqueue.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_mutex.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_once.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_semaphore.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_stdbool.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_stdint.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_string.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_thread.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_thread_attr.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_timer.h
- create mode 100644 drivers/misc/vc04_services/interface/vcos/vcos_types.h
-
---- a/drivers/misc/Kconfig
-+++ b/drivers/misc/Kconfig
-@@ -506,4 +506,5 @@ source "drivers/misc/ti-st/Kconfig"
- source "drivers/misc/lis3lv02d/Kconfig"
- source "drivers/misc/carma/Kconfig"
- source "drivers/misc/altera-stapl/Kconfig"
-+source "drivers/misc/vc04_services/Kconfig"
- endmenu
---- a/drivers/misc/Makefile
-+++ b/drivers/misc/Makefile
-@@ -49,3 +49,5 @@ obj-y                                += carma/
- obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
- obj-$(CONFIG_ALTERA_STAPL)    +=altera-stapl/
- obj-$(CONFIG_MAX8997_MUIC)    += max8997-muic.o
-+obj-y                          += vc04_services/
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/Kconfig
-@@ -0,0 +1,7 @@
-+config BCM2708_VCHIQ
-+      tristate "Videocore VCHIQ"
-+      depends on MACH_BCM2708
-+        default y
-+        help
-+          Helper for communication for VideoCore.
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/Makefile
-@@ -0,0 +1,19 @@
-+obj-$(CONFIG_BCM2708_VCHIQ)   += vchiq.o
-+
-+vchiq-objs := \
-+   interface/vchiq_arm/vchiq_core.o  \
-+   interface/vchiq_arm/vchiq_arm.o \
-+   interface/vchiq_arm/vchiq_kern_lib.o \
-+   interface/vchiq_arm/vchiq_2835_arm.o \
-+   interface/vcos/linuxkernel/vcos_linuxkernel.o \
-+   interface/vcos/linuxkernel/vcos_thread_map.o \
-+   interface/vcos/linuxkernel/vcos_linuxkernel_cfg.o \
-+   interface/vcos/generic/vcos_generic_event_flags.o \
-+   interface/vcos/generic/vcos_logcat.o \
-+   interface/vcos/generic/vcos_mem_from_malloc.o \
-+   interface/vcos/generic/vcos_cmd.o
-+
-+EXTRA_CFLAGS += -DVCOS_VERIFY_BKPTS=1 -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel
-+
-+
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchi/vchi_mh.h
-@@ -0,0 +1,19 @@
-+/*=============================================================================
-+Copyright (c) 2010 Broadcom Europe Limited. All rights reserved.
-+
-+Project  :  vchi
-+Module   :  vchi
-+
-+FILE DESCRIPTION:
-+Definitions for memory handle types.
-+=============================================================================*/
-+
-+#ifndef VCHI_MH_H_
-+#define VCHI_MH_H_
-+
-+#include <interface/vcos/vcos.h>
-+
-+typedef int32_t VCHI_MEM_HANDLE_T;
-+#define VCHI_MEM_HANDLE_INVALID 0
-+
-+#endif
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h
-@@ -0,0 +1,27 @@
-+/*
-+ * Copyright (c) 2010-2011 Broadcom. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#ifndef VCHIQ_VCHIQ_H
-+#define VCHIQ_VCHIQ_H
-+
-+#include "vchiq_if.h"
-+#include "vchiq_util.h"
-+#include "interface/vcos/vcos.h"
-+
-+#endif
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h
-@@ -0,0 +1,27 @@
-+/*
-+ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#ifndef VCHIQ_2835_H
-+#define VCHIQ_2835_H
-+
-+#include "vchiq_pagelist.h"
-+
-+#define VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX 0
-+#define VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX  1
-+
-+#endif /* VCHIQ_2835_H */
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
-@@ -0,0 +1,487 @@
-+/*
-+ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/types.h>
-+#include <linux/errno.h>
-+#include <linux/interrupt.h>
-+#include <linux/irq.h>
-+#include <linux/pagemap.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/version.h>
-+#include <asm/pgtable.h>
-+#include <asm/io.h>
-+#include <asm/uaccess.h>
-+
-+#include <mach/irqs.h>
-+
-+#include <mach/platform.h>
-+#include <mach/vcio.h>
-+
-+#define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32)
-+
-+#define VCHIQ_DOORBELL_IRQ IRQ_ARM_DOORBELL_0
-+#define VCHIQ_ARM_ADDRESS(x) __virt_to_bus(x)
-+
-+#include "vchiq_arm.h"
-+#include "vchiq_2835.h"
-+
-+#define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2)
-+
-+#define VCOS_LOG_CATEGORY (&vchiq_arm_log_category)
-+
-+static char *g_slot_mem;
-+static int g_slot_mem_size;
-+dma_addr_t g_slot_phys;
-+static FRAGMENTS_T *g_fragments_base;
-+static FRAGMENTS_T *g_free_fragments;
-+struct semaphore g_free_fragments_sema;
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
-+static DEFINE_SEMAPHORE(g_free_fragments_mutex);
-+#else
-+static DECLARE_MUTEX(g_free_fragments_mutex);
-+#endif
-+
-+static irqreturn_t
-+vchiq_doorbell_irq(int irq, void *dev_id);
-+
-+static int
-+create_pagelist(char __user *buf, size_t count, unsigned short type,
-+      struct task_struct *task, PAGELIST_T ** ppagelist);
-+
-+static void
-+free_pagelist(PAGELIST_T *pagelist, int actual);
-+
-+int __init
-+vchiq_platform_vcos_init(void)
-+{
-+      return (vcos_init() == VCOS_SUCCESS) ? 0 : -EINVAL;
-+}
-+
-+int __init
-+vchiq_platform_init(VCHIQ_STATE_T *state)
-+{
-+      VCHIQ_SLOT_ZERO_T *vchiq_slot_zero;
-+      int frag_mem_size;
-+      int err;
-+      int i;
-+
-+      /* Allocate space for the channels in coherent memory */
-+      g_slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE);
-+      frag_mem_size = PAGE_ALIGN(sizeof(FRAGMENTS_T) * MAX_FRAGMENTS);
-+
-+      g_slot_mem = dma_alloc_coherent(NULL, g_slot_mem_size + frag_mem_size,
-+              &g_slot_phys, GFP_ATOMIC);
-+
-+      if (!g_slot_mem) {
-+              vcos_log_error("Unable to allocate channel memory");
-+              err = -ENOMEM;
-+              goto failed_alloc;
-+      }
-+
-+      vcos_assert(((int)g_slot_mem & (PAGE_SIZE - 1)) == 0);
-+
-+      vchiq_slot_zero = vchiq_init_slots(g_slot_mem, g_slot_mem_size);
-+      if (!vchiq_slot_zero)
-+      {
-+         err = -EINVAL;
-+         goto failed_init_slots;
-+      }
-+
-+      vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] = (int)g_slot_phys + g_slot_mem_size;
-+      vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] = MAX_FRAGMENTS;
-+
-+      g_fragments_base = (FRAGMENTS_T *)(g_slot_mem + g_slot_mem_size);
-+      g_slot_mem_size += frag_mem_size;
-+
-+      g_free_fragments = g_fragments_base;
-+      for (i = 0; i < (MAX_FRAGMENTS - 1); i++) {
-+              *(FRAGMENTS_T **) & g_fragments_base[i] =
-+                      &g_fragments_base[i + 1];
-+      }
-+      *(FRAGMENTS_T **) & g_fragments_base[i] = NULL;
-+      sema_init(&g_free_fragments_sema, MAX_FRAGMENTS);
-+
-+      if (vchiq_init_state(state, vchiq_slot_zero, 0/*slave*/) !=
-+              VCHIQ_SUCCESS)
-+      {
-+              err = -EINVAL;
-+              goto failed_vchiq_init;
-+      }
-+
-+      err = request_irq(VCHIQ_DOORBELL_IRQ, vchiq_doorbell_irq,
-+              IRQF_IRQPOLL, "VCHIQ doorbell",
-+              state);
-+      if (err < 0)
-+      {
-+              printk( KERN_ERR "%s: failed to register irq=%d err=%d\n", __func__,
-+                      VCHIQ_DOORBELL_IRQ, err );
-+              goto failed_request_irq;
-+      }
-+
-+      /* Send the base address of the slots to VideoCore */
-+
-+      dsb(); /* Ensure all writes have completed */
-+
-+      bcm_mailbox_write(MBOX_CHAN_VCHIQ, (unsigned int)g_slot_phys);
-+
-+      vcos_log_info("vchiq_init - done (slots %x, phys %x)",
-+              (unsigned int)vchiq_slot_zero, g_slot_phys);
-+
-+      return 0;
-+
-+failed_request_irq:
-+failed_vchiq_init:
-+failed_init_slots:
-+      dma_free_coherent(NULL, g_slot_mem_size, g_slot_mem, g_slot_phys);
-+
-+failed_alloc:
-+      return err;
-+}
-+
-+void __exit
-+vchiq_platform_exit(VCHIQ_STATE_T *state)
-+{
-+      free_irq(VCHIQ_DOORBELL_IRQ, state);
-+      dma_free_coherent(NULL, g_slot_mem_size,
-+              g_slot_mem, g_slot_phys);
-+}
-+
-+void
-+remote_event_signal(REMOTE_EVENT_T *event)
-+{
-+      event->fired = 1;
-+
-+      /* The test on the next line also ensures the write on the previous line
-+              has completed */
-+
-+      if (event->armed) {
-+              /* trigger vc interrupt */
-+              dsb();         /* data barrier operation */
-+
-+              writel(0, __io_address(ARM_0_BELL2));
-+      }
-+}
-+
-+int
-+vchiq_copy_from_user(void *dst, const void *src, int size)
-+{
-+      return copy_from_user(dst, src, size);
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, VCHI_MEM_HANDLE_T memhandle,
-+      void *offset, int size, int dir)
-+{
-+      PAGELIST_T *pagelist;
-+      int ret;
-+
-+      vcos_assert(memhandle == VCHI_MEM_HANDLE_INVALID);
-+
-+      ret = create_pagelist((char __user *)offset, size,
-+                      (dir == VCHIQ_BULK_RECEIVE)
-+                      ? PAGELIST_READ
-+                      : PAGELIST_WRITE,
-+                      current,
-+                      &pagelist);
-+      if (ret != 0)
-+              return VCHIQ_ERROR;
-+
-+      bulk->handle = memhandle;
-+      bulk->data = VCHIQ_ARM_ADDRESS(pagelist);
-+
-+      /* Store the pagelist address in remote_data, which isn't used by the
-+         slave. */
-+      bulk->remote_data = pagelist;
-+
-+      return VCHIQ_SUCCESS;
-+}
-+
-+void
-+vchiq_complete_bulk(VCHIQ_BULK_T *bulk)
-+{
-+      free_pagelist((PAGELIST_T *)bulk->remote_data, bulk->actual);
-+}
-+
-+void
-+vchiq_transfer_bulk(VCHIQ_BULK_T *bulk)
-+{
-+      /*
-+       * This should only be called on the master (VideoCore) side, but
-+       * provide an implementation to avoid the need for ifdefery.
-+       */
-+      vcos_assert(!"This code should not be called by the ARM on BCM2835");
-+}
-+
-+void
-+vchiq_dump_platform_state(void *dump_context)
-+{
-+        char buf[80];
-+        int len;
-+        len = vcos_snprintf(buf, sizeof(buf),
-+                "  Platform: 2835 (VC master)");
-+        vchiq_dump(dump_context, buf, len + 1);
-+}
-+
-+void
-+vchiq_platform_paused(VCHIQ_STATE_T *state)
-+{
-+   vcos_unused(state);
-+   vcos_assert_msg(0, "Suspend/resume not supported");
-+}
-+
-+void
-+vchiq_platform_resumed(VCHIQ_STATE_T *state)
-+{
-+   vcos_unused(state);
-+   vcos_assert_msg(0, "Suspend/resume not supported");
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle)
-+{
-+   VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
-+   if (!service)
-+      return VCHIQ_ERROR;
-+   return VCHIQ_SUCCESS;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle)
-+{
-+   VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
-+   if (!service)
-+      return VCHIQ_ERROR;
-+   return VCHIQ_SUCCESS;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_check_service(VCHIQ_SERVICE_HANDLE_T handle)
-+{
-+   VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
-+   if (!service)
-+      return VCHIQ_ERROR;
-+   return VCHIQ_SUCCESS;
-+}
-+
-+/*
-+ * Local functions
-+ */
-+
-+static irqreturn_t
-+vchiq_doorbell_irq(int irq, void *dev_id)
-+{
-+   VCHIQ_STATE_T *state = dev_id;
-+      irqreturn_t ret = IRQ_NONE;
-+      unsigned int status;
-+
-+      /* Read (and clear) the doorbell */
-+      status = readl(__io_address(ARM_0_BELL0));
-+
-+      if (status & 0x4) {  /* Was the doorbell rung? */
-+              remote_event_pollall(state);
-+              ret = IRQ_HANDLED;
-+      }
-+
-+      return ret;
-+}
-+
-+/* There is a potential problem with partial cache lines (pages?)
-+      at the ends of the block when reading. If the CPU accessed anything in
-+      the same line (page?) then it may have pulled old data into the cache,
-+      obscuring the new data underneath. We can solve this by transferring the
-+      partial cache lines separately, and allowing the ARM to copy into the
-+      cached area.
-+
-+      N.B. This implementation plays slightly fast and loose with the Linux
-+      driver programming rules, e.g. its use of __virt_to_bus instead of
-+      dma_map_single, but it isn't a multi-platform driver and it benefits
-+      from increased speed as a result.
-+ */
-+
-+static int
-+create_pagelist(char __user *buf, size_t count, unsigned short type,
-+      struct task_struct *task, PAGELIST_T ** ppagelist)
-+{
-+      PAGELIST_T *pagelist;
-+      struct page **pages;
-+      struct page *page;
-+      unsigned long *addrs;
-+      unsigned int num_pages, offset, i;
-+      char *addr, *base_addr, *next_addr;
-+      int run, addridx, actual_pages;
-+
-+      offset = (unsigned int)buf & (PAGE_SIZE - 1);
-+      num_pages = (count + offset + PAGE_SIZE - 1) / PAGE_SIZE;
-+
-+      *ppagelist = NULL;
-+
-+      /* Allocate enough storage to hold the page pointers and the page list */
-+      pagelist = (PAGELIST_T *) kmalloc(sizeof(PAGELIST_T) +
-+              (num_pages * sizeof(unsigned long)) +
-+              (num_pages * sizeof(pages[0])),
-+              GFP_KERNEL);
-+
-+      vcos_log_trace("create_pagelist - %x", (unsigned int)pagelist);
-+      if (!pagelist)
-+              return -ENOMEM;
-+
-+      addrs = pagelist->addrs;
-+      pages = (struct page **)(addrs + num_pages);
-+
-+      down_read(&task->mm->mmap_sem);
-+      actual_pages = get_user_pages(task, task->mm,
-+              (unsigned long)buf & ~(PAGE_SIZE - 1), num_pages,
-+              (type == PAGELIST_READ) /*Write */ , 0 /*Force */ ,
-+              pages, NULL /*vmas */ );
-+      up_read(&task->mm->mmap_sem);
-+
-+        if (actual_pages != num_pages)
-+      {
-+              for (i = 0; i < actual_pages; i++) {
-+                      page_cache_release(pages[i]);
-+              }
-+              kfree(pagelist);
-+              return -EINVAL;
-+      }
-+
-+      pagelist->length = count;
-+      pagelist->type = type;
-+      pagelist->offset = offset;
-+
-+      /* Group the pages into runs of contiguous pages */
-+
-+      base_addr = VCHIQ_ARM_ADDRESS(page_address(pages[0]));
-+      next_addr = base_addr + PAGE_SIZE;
-+      addridx = 0;
-+      run = 0;
-+
-+      for (i = 1; i < num_pages; i++) {
-+              addr = VCHIQ_ARM_ADDRESS(page_address(pages[i]));
-+              if ((addr == next_addr) && (run < (PAGE_SIZE - 1))) {
-+                      next_addr += PAGE_SIZE;
-+                      run++;
-+              } else {
-+                      addrs[addridx] = (unsigned long)base_addr + run;
-+                      addridx++;
-+                      base_addr = addr;
-+                      next_addr = addr + PAGE_SIZE;
-+                      run = 0;
-+              }
-+      }
-+
-+      addrs[addridx] = (unsigned long)base_addr + run;
-+      addridx++;
-+
-+      /* Partial cache lines (fragments) require special measures */
-+      if ((type == PAGELIST_READ) &&
-+              ((pagelist->offset & (CACHE_LINE_SIZE - 1)) ||
-+              ((pagelist->offset + pagelist->length) & (CACHE_LINE_SIZE - 1)))) {
-+              FRAGMENTS_T *fragments;
-+
-+              if (down_interruptible(&g_free_fragments_sema) != 0) {
-+                      kfree(pagelist);
-+                      return -EINTR;
-+              }
-+
-+              vcos_assert(g_free_fragments != NULL);
-+
-+              down(&g_free_fragments_mutex);
-+              fragments = (FRAGMENTS_T *) g_free_fragments;
-+              vcos_assert(fragments != NULL);
-+              g_free_fragments = *(FRAGMENTS_T **) g_free_fragments;
-+              up(&g_free_fragments_mutex);
-+              pagelist->type =
-+                       PAGELIST_READ_WITH_FRAGMENTS + (fragments -
-+                                                       g_fragments_base);
-+      }
-+
-+      for (page = virt_to_page(pagelist);
-+              page <= virt_to_page(addrs + num_pages - 1); page++) {
-+              flush_dcache_page(page);
-+      }
-+
-+      *ppagelist = pagelist;
-+
-+      return 0;
-+}
-+
-+static void
-+free_pagelist(PAGELIST_T *pagelist, int actual)
-+{
-+      struct page **pages;
-+      unsigned int num_pages, i;
-+
-+      vcos_log_trace("free_pagelist - %x, %d", (unsigned int)pagelist, actual);
-+
-+      num_pages =
-+               (pagelist->length + pagelist->offset + PAGE_SIZE - 1) / PAGE_SIZE;
-+
-+      pages = (struct page **)(pagelist->addrs + num_pages);
-+
-+      /* Deal with any partial cache lines (fragments) */
-+      if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS) {
-+              FRAGMENTS_T *fragments =
-+                       g_fragments_base + (pagelist->type -
-+                                      PAGELIST_READ_WITH_FRAGMENTS);
-+              int head_bytes, tail_bytes;
-+
-+              if (actual >= 0)
-+              {
-+                      if ((head_bytes = (CACHE_LINE_SIZE - pagelist->offset) & (CACHE_LINE_SIZE - 1)) != 0) {
-+                              if (head_bytes > actual)
-+                                      head_bytes = actual;
-+
-+                              memcpy((char *)page_address(pages[0]) +
-+                                               pagelist->offset, fragments->headbuf,
-+                                               head_bytes);
-+                      }
-+                      if ((head_bytes < actual) &&
-+                              (tail_bytes =
-+                              (pagelist->offset + actual) & (CACHE_LINE_SIZE -
-+                                                                              1)) != 0) {
-+                              memcpy((char *)page_address(pages[num_pages - 1]) +
-+                                               ((pagelist->offset + actual) & (PAGE_SIZE -
-+                                                                      1) & ~(CACHE_LINE_SIZE - 1)),
-+                                               fragments->tailbuf, tail_bytes);
-+                      }
-+              }
-+
-+              down(&g_free_fragments_mutex);
-+              *(FRAGMENTS_T **) fragments = g_free_fragments;
-+              g_free_fragments = fragments;
-+              up(&g_free_fragments_mutex);
-+              up(&g_free_fragments_sema);
-+      }
-+
-+      for (i = 0; i < num_pages; i++) {
-+              if (pagelist->type != PAGELIST_WRITE)
-+                      set_page_dirty(pages[i]);
-+              page_cache_release(pages[i]);
-+      }
-+
-+      kfree(pagelist);
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_platform_suspend(VCHIQ_STATE_T *state)
-+{
-+   vcos_unused(state);
-+   return VCHIQ_ERROR;
-+}
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c
-@@ -0,0 +1,1293 @@
-+/*
-+ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/errno.h>
-+#include <linux/cdev.h>
-+#include <linux/fs.h>
-+#include <linux/device.h>
-+
-+#include "vchiq_core.h"
-+#include "vchiq_ioctl.h"
-+#include "vchiq_arm.h"
-+
-+#define DEVICE_NAME "vchiq"
-+
-+/* Override the default prefix, which would be vchiq_arm (from the filename) */
-+#undef MODULE_PARAM_PREFIX
-+#define MODULE_PARAM_PREFIX DEVICE_NAME "."
-+
-+#define VCHIQ_MINOR 0
-+
-+/* Some per-instance constants */
-+#define MAX_COMPLETIONS 16
-+#define MAX_SERVICES 64
-+#define MAX_ELEMENTS 8
-+#define MSG_QUEUE_SIZE 64
-+
-+#define VCOS_LOG_CATEGORY (&vchiq_arm_log_category)
-+
-+typedef struct client_service_struct {
-+   VCHIQ_SERVICE_T *service;
-+   void *userdata;
-+   VCHIQ_INSTANCE_T instance;
-+   int handle;
-+   int is_vchi;
-+   volatile int dequeue_pending;
-+   volatile int message_available_pos;
-+   volatile int msg_insert;
-+   volatile int msg_remove;
-+   VCOS_EVENT_T insert_event;
-+   VCOS_EVENT_T remove_event;
-+   VCHIQ_HEADER_T *msg_queue[MSG_QUEUE_SIZE];
-+} USER_SERVICE_T;
-+
-+struct vchiq_instance_struct {
-+   VCHIQ_STATE_T *state;
-+   VCHIQ_COMPLETION_DATA_T completions[MAX_COMPLETIONS];
-+   volatile int completion_insert;
-+   volatile int completion_remove;
-+   VCOS_EVENT_T insert_event;
-+   VCOS_EVENT_T remove_event;
-+
-+   USER_SERVICE_T services[MAX_SERVICES];
-+
-+   int connected;
-+   int closing;
-+   int pid;
-+   int mark;
-+};
-+
-+typedef struct dump_context_struct
-+{
-+   char __user *buf;
-+   size_t actual;
-+   size_t space;
-+   loff_t offset;
-+} DUMP_CONTEXT_T;
-+
-+VCOS_LOG_CAT_T vchiq_arm_log_category;
-+
-+static struct cdev    vchiq_cdev;
-+static dev_t          vchiq_devid;
-+static VCHIQ_STATE_T g_state;
-+static struct class  *vchiq_class;
-+static struct device *vchiq_dev;
-+
-+static const char *ioctl_names[] =
-+{
-+   "CONNECT",
-+   "SHUTDOWN",
-+   "CREATE_SERVICE",
-+   "REMOVE_SERVICE",
-+   "QUEUE_MESSAGE",
-+   "QUEUE_BULK_TRANSMIT",
-+   "QUEUE_BULK_RECEIVE",
-+   "AWAIT_COMPLETION",
-+   "DEQUEUE_MESSAGE",
-+   "GET_CLIENT_ID",
-+   "GET_CONFIG",
-+   "CLOSE_SERVICE",
-+   "USE_SERVICE",
-+   "RELEASE_SERIVCE"
-+};
-+
-+VCOS_LOG_LEVEL_T vchiq_default_arm_log_level = VCOS_LOG_WARN;
-+
-+/****************************************************************************
-+*
-+*   find_service_by_handle
-+*
-+***************************************************************************/
-+
-+static inline USER_SERVICE_T *find_service_by_handle(
-+      VCHIQ_INSTANCE_T instance, int handle )
-+{
-+   USER_SERVICE_T *user_service;
-+
-+   if (( handle >= 0 )
-+      && ( handle < MAX_SERVICES ))
-+   {
-+      user_service = &instance->services[ handle ];
-+
-+      if ( user_service->service != NULL )
-+      {
-+         return user_service;
-+      }
-+   }
-+
-+   return NULL;
-+}
-+
-+/****************************************************************************
-+*
-+*   find_avail_service_handle
-+*
-+***************************************************************************/
-+
-+static inline USER_SERVICE_T *find_avail_service_handle(
-+   VCHIQ_INSTANCE_T instance)
-+{
-+   int handle;
-+
-+   for ( handle = 0; handle < MAX_SERVICES; handle++ )
-+   {
-+      if ( instance->services[handle].service == NULL )
-+      {
-+         instance->services[handle].instance = instance;
-+         instance->services[handle].handle = handle;
-+
-+         return &instance->services[handle];
-+      }
-+   }
-+   return NULL;
-+}
-+
-+/****************************************************************************
-+*
-+*   add_completion
-+*
-+***************************************************************************/
-+
-+static VCHIQ_STATUS_T
-+add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason,
-+   VCHIQ_HEADER_T *header, USER_SERVICE_T *service, void *bulk_userdata)
-+{
-+   VCHIQ_COMPLETION_DATA_T *completion;
-+   DEBUG_INITIALISE(g_state.local)
-+
-+   while (instance->completion_insert ==
-+          (instance->completion_remove + MAX_COMPLETIONS)) {
-+      /* Out of space - wait for the client */
-+      DEBUG_TRACE(SERVICE_CALLBACK_LINE);
-+      vcos_log_trace("add_completion - completion queue full");
-+      DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT);
-+      if (vcos_event_wait(&instance->remove_event) != VCOS_SUCCESS) {
-+         vcos_log_info("service_callback interrupted");
-+         return VCHIQ_RETRY;
-+      } else if (instance->closing) {
-+         vcos_log_info("service_callback closing");
-+         return VCHIQ_ERROR;
-+      }
-+      DEBUG_TRACE(SERVICE_CALLBACK_LINE);
-+   }
-+
-+   completion =
-+       &instance->
-+       completions[instance->completion_insert & (MAX_COMPLETIONS - 1)];
-+
-+   completion->header = header;
-+   completion->reason = reason;
-+   completion->service_userdata = service;
-+   completion->bulk_userdata = bulk_userdata;
-+
-+   /* A write barrier is needed here to ensure that the entire completion
-+      record is written out before the insert point. */
-+   vcos_wmb(&completion->bulk_userdata);
-+
-+   if (reason == VCHIQ_MESSAGE_AVAILABLE)
-+      service->message_available_pos = instance->completion_insert;
-+   instance->completion_insert++;
-+
-+   vcos_event_signal(&instance->insert_event);
-+
-+   return VCHIQ_SUCCESS;
-+}
-+
-+/****************************************************************************
-+*
-+*   service_callback
-+*
-+***************************************************************************/
-+
-+static VCHIQ_STATUS_T
-+service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header,
-+   VCHIQ_SERVICE_HANDLE_T handle, void *bulk_userdata)
-+{
-+   /* How do we ensure the callback goes to the right client?
-+      The service_user data points to a USER_SERVICE_T record containing the
-+      original callback and the user state structure, which contains a circular
-+      buffer for completion records.
-+    */
-+   USER_SERVICE_T *service =
-+       (USER_SERVICE_T *) VCHIQ_GET_SERVICE_USERDATA(handle);
-+   VCHIQ_INSTANCE_T instance = service->instance;
-+   DEBUG_INITIALISE(g_state.local)
-+
-+   DEBUG_TRACE(SERVICE_CALLBACK_LINE);
-+   vcos_log_trace
-+       ("service_callback - service %lx(%d), reason %d, header %lx, "
-+        "instance %lx, bulk_userdata %lx",
-+        (unsigned long)service, ((VCHIQ_SERVICE_T *) handle)->localport,
-+        reason, (unsigned long)header,
-+        (unsigned long)instance, (unsigned long)bulk_userdata);
-+
-+   if (!instance || instance->closing) {
-+      return VCHIQ_SUCCESS;
-+   }
-+
-+   if (header && service->is_vchi)
-+   {
-+      while (service->msg_insert == (service->msg_remove + MSG_QUEUE_SIZE))
-+      {
-+         DEBUG_TRACE(SERVICE_CALLBACK_LINE);
-+         DEBUG_COUNT(MSG_QUEUE_FULL_COUNT);
-+         vcos_log_trace("service_callback - msg queue full");
-+         /* If there is no MESSAGE_AVAILABLE in the completion queue, add one */
-+         if ((service->message_available_pos - instance->completion_remove) < 0)
-+         {
-+            VCHIQ_STATUS_T status;
-+            vcos_log_warn("Inserting extra MESSAGE_AVAILABLE");
-+            DEBUG_TRACE(SERVICE_CALLBACK_LINE);
-+            status = add_completion(instance, reason, NULL, service, bulk_userdata);
-+            if (status != VCHIQ_SUCCESS)
-+            {
-+               DEBUG_TRACE(SERVICE_CALLBACK_LINE);
-+               return status;
-+            }
-+         }
-+         
-+         DEBUG_TRACE(SERVICE_CALLBACK_LINE);
-+         if (vcos_event_wait(&service->remove_event) != VCOS_SUCCESS) {
-+            vcos_log_info("service_callback interrupted");
-+            DEBUG_TRACE(SERVICE_CALLBACK_LINE);
-+            return VCHIQ_RETRY;
-+         } else if (instance->closing) {
-+            vcos_log_info("service_callback closing");
-+            DEBUG_TRACE(SERVICE_CALLBACK_LINE);
-+            return VCHIQ_ERROR;
-+         }
-+         DEBUG_TRACE(SERVICE_CALLBACK_LINE);
-+      }
-+
-+      service->msg_queue[service->msg_insert & (MSG_QUEUE_SIZE - 1)] =
-+         header;
-+
-+      /* A write memory barrier is needed to ensure that the store of header
-+         is completed before the insertion point is updated */
-+      vcos_wmb(&service->msg_queue[service->msg_insert & (MSG_QUEUE_SIZE - 1)]);
-+
-+      service->msg_insert++;
-+      vcos_event_signal(&service->insert_event);
-+
-+      /* If there is a thread waiting in DEQUEUE_MESSAGE, or if
-+         there is a MESSAGE_AVAILABLE in the completion queue then
-+         bypass the completion queue. */
-+      if (((service->message_available_pos - instance->completion_remove) >= 0) ||
-+          service->dequeue_pending)
-+      {
-+         DEBUG_TRACE(SERVICE_CALLBACK_LINE);
-+         service->dequeue_pending = 0;
-+         return VCHIQ_SUCCESS;
-+      }
-+
-+      header = NULL;
-+   }
-+   DEBUG_TRACE(SERVICE_CALLBACK_LINE);
-+
-+   return add_completion(instance, reason, header, service, bulk_userdata);
-+}
-+
-+/****************************************************************************
-+*
-+*   vchiq_ioctl
-+*
-+***************************************************************************/
-+
-+static long
-+vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+   VCHIQ_INSTANCE_T instance = file->private_data;
-+   VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
-+   long ret = 0;
-+   int i, rc;
-+   DEBUG_INITIALISE(g_state.local)
-+
-+   vcos_log_trace("vchiq_ioctl - instance %x, cmd %s, arg %lx",
-+      (unsigned int)instance,
-+      ((_IOC_TYPE(cmd) == VCHIQ_IOC_MAGIC) && (_IOC_NR(cmd) <= VCHIQ_IOC_MAX)) ?
-+      ioctl_names[_IOC_NR(cmd)] : "<invalid>", arg);
-+
-+   switch (cmd) {
-+   case VCHIQ_IOC_SHUTDOWN:
-+      if (!instance->connected)
-+         break;
-+
-+      /* Remove all services */
-+      for (i = 0; i < MAX_SERVICES; i++) {
-+         USER_SERVICE_T *service = &instance->services[i];
-+         if (service->service != NULL) {
-+            status = vchiq_remove_service(&service->service->base);
-+            if (status != VCHIQ_SUCCESS)
-+               break;
-+            service->service = NULL;
-+         }
-+      }
-+
-+      if (status == VCHIQ_SUCCESS) {
-+         /* Wake the completion thread and ask it to exit */
-+         instance->closing = 1;
-+         vcos_event_signal(&instance->insert_event);
-+      }
-+
-+      break;
-+
-+   case VCHIQ_IOC_CONNECT:
-+      if (instance->connected) {
-+         ret = -EINVAL;
-+         break;
-+      }
-+      if ((rc=vcos_mutex_lock(&instance->state->mutex)) != VCOS_SUCCESS) {
-+         vcos_log_error("vchiq: connect: could not lock mutex for state %d: %d",
-+                        instance->state->id, rc);
-+         ret = -EINTR;
-+         break;
-+      }
-+      status = vchiq_connect_internal(instance->state, instance);
-+      vcos_mutex_unlock(&instance->state->mutex);
-+
-+      if (status == VCHIQ_SUCCESS)
-+         instance->connected = 1;
-+      else
-+         vcos_log_error("vchiq: could not connect: %d", status);
-+      break;
-+
-+   case VCHIQ_IOC_CREATE_SERVICE:
-+      {
-+         VCHIQ_CREATE_SERVICE_T args;
-+         VCHIQ_SERVICE_T *service = NULL;
-+         USER_SERVICE_T *user_service = NULL;
-+         void *userdata;
-+         int srvstate;
-+
-+         if (copy_from_user
-+             (&args, (const void __user *)arg,
-+              sizeof(args)) != 0) {
-+            ret = -EFAULT;
-+            break;
-+         }
-+
-+         for (i = 0; i < MAX_SERVICES; i++) {
-+            if (instance->services[i].service == NULL) {
-+               user_service = &instance->services[i];
-+               break;
-+            }
-+         }
-+
-+         if (!user_service) {
-+            ret = -EMFILE;
-+            break;
-+         }
-+
-+         if (args.is_open) {
-+            if (instance->connected)
-+               srvstate = VCHIQ_SRVSTATE_OPENING;
-+            else {
-+               ret = -ENOTCONN;
-+               break;
-+            }
-+         } else {
-+            srvstate =
-+                instance->connected ?
-+                VCHIQ_SRVSTATE_LISTENING :
-+                VCHIQ_SRVSTATE_HIDDEN;
-+         }
-+
-+         vcos_mutex_lock(&instance->state->mutex);
-+
-+         userdata = args.params.userdata;
-+         args.params.callback = service_callback;
-+         args.params.userdata = user_service;
-+         service =
-+             vchiq_add_service_internal(instance->state,
-+                         &args.params, srvstate,
-+                         instance);
-+
-+         vcos_mutex_unlock(&instance->state->mutex);
-+
-+         if (service != NULL) {
-+            user_service->service = service;
-+            user_service->userdata = userdata;
-+            user_service->instance = instance;
-+            user_service->handle = i;
-+            user_service->is_vchi = args.is_vchi;
-+            user_service->dequeue_pending = 0;
-+            user_service->message_available_pos = instance->completion_remove - 1;
-+            user_service->msg_insert = 0;
-+            user_service->msg_remove = 0;
-+            vcos_event_create(&user_service->insert_event, "insert_event");
-+            vcos_event_create(&user_service->remove_event, "remove_event");
-+
-+            if (args.is_open) {
-+               status =
-+                   vchiq_open_service_internal
-+                   (service, instance->pid);
-+               if (status != VCHIQ_SUCCESS) {
-+                  vchiq_remove_service
-+                      (&service->base);
-+                  ret =
-+                      (status ==
-+                       VCHIQ_RETRY) ? -EINTR :
-+                      -EIO;
-+                  user_service->service = NULL;
-+                  user_service->instance = NULL;
-+                  vcos_event_delete(&user_service->insert_event);
-+                  vcos_event_delete(&user_service->remove_event);
-+                  break;
-+               }
-+            }
-+
-+            if (copy_to_user((void __user *)
-+                   &(((VCHIQ_CREATE_SERVICE_T __user
-+                       *) arg)->handle),
-+                   (const void *)&user_service->
-+                   handle,
-+                   sizeof(user_service->
-+                     handle)) != 0)
-+               ret = -EFAULT;
-+         } else {
-+            ret = -EEXIST;
-+         }
-+      }
-+      break;
-+
-+   case VCHIQ_IOC_CLOSE_SERVICE:
-+      {
-+         USER_SERVICE_T *user_service;
-+         int handle = (int)arg;
-+
-+         user_service = find_service_by_handle(instance, handle);
-+         if (user_service != NULL)
-+         {
-+            int is_server = (user_service->service->public_fourcc != VCHIQ_FOURCC_INVALID);
-+
-+            status =
-+                vchiq_close_service(&user_service->service->base);
-+            if ((status == VCHIQ_SUCCESS) && !is_server)
-+            {
-+               vcos_event_delete(&user_service->insert_event);
-+               vcos_event_delete(&user_service->remove_event);
-+               user_service->service = NULL;
-+            }
-+         } else
-+            ret = -EINVAL;
-+      }
-+      break;
-+
-+   case VCHIQ_IOC_REMOVE_SERVICE:
-+      {
-+         USER_SERVICE_T *user_service;
-+         int handle = (int)arg;
-+
-+         user_service = find_service_by_handle(instance, handle);
-+         if (user_service != NULL)
-+         {
-+            status =
-+                vchiq_remove_service(&user_service->service->base);
-+            if (status == VCHIQ_SUCCESS)
-+            {
-+               vcos_event_delete(&user_service->insert_event);
-+               vcos_event_delete(&user_service->remove_event);
-+               user_service->service = NULL;
-+            }
-+         } else
-+            ret = -EINVAL;
-+      }
-+      break;
-+
-+   case VCHIQ_IOC_USE_SERVICE:
-+   case VCHIQ_IOC_RELEASE_SERVICE:
-+      {
-+         USER_SERVICE_T *user_service;
-+         int handle = (int)arg;
-+
-+         user_service = find_service_by_handle(instance, handle);
-+         if (user_service != NULL)
-+         {
-+            status = (cmd == VCHIQ_IOC_USE_SERVICE) ? vchiq_use_service(&user_service->service->base) : vchiq_release_service(&user_service->service->base);
-+            if (status != VCHIQ_SUCCESS)
-+            {
-+               ret = -EINVAL; // ???
-+            }
-+         }
-+      }
-+      break;
-+
-+   case VCHIQ_IOC_QUEUE_MESSAGE:
-+      {
-+         VCHIQ_QUEUE_MESSAGE_T args;
-+         USER_SERVICE_T *user_service;
-+
-+         if (copy_from_user
-+             (&args, (const void __user *)arg,
-+              sizeof(args)) != 0) {
-+            ret = -EFAULT;
-+            break;
-+         }
-+         user_service = find_service_by_handle(instance, args.handle);
-+         if ((user_service != NULL) && (args.count <= MAX_ELEMENTS))
-+         {
-+            /* Copy elements into kernel space */
-+            VCHIQ_ELEMENT_T elements[MAX_ELEMENTS];
-+            if (copy_from_user
-+                (elements, args.elements,
-+                 args.count * sizeof(VCHIQ_ELEMENT_T)) == 0)
-+               status =
-+                  vchiq_queue_message
-+                  (&user_service->service->base,
-+                   elements, args.count);
-+            else
-+               ret = -EFAULT;
-+         } else {
-+            ret = -EINVAL;
-+         }
-+      }
-+      break;
-+
-+   case VCHIQ_IOC_QUEUE_BULK_TRANSMIT:
-+   case VCHIQ_IOC_QUEUE_BULK_RECEIVE:
-+      {
-+         VCHIQ_QUEUE_BULK_TRANSFER_T args;
-+         USER_SERVICE_T *user_service;
-+         VCHIQ_BULK_DIR_T dir =
-+           (cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT) ?
-+           VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE;
-+
-+         if (copy_from_user
-+             (&args, (const void __user *)arg,
-+              sizeof(args)) != 0) {
-+            ret = -EFAULT;
-+            break;
-+         }
-+         user_service = find_service_by_handle(instance, args.handle);
-+         if (user_service != NULL)
-+         {
-+            status =
-+               vchiq_bulk_transfer
-+               ((VCHIQ_SERVICE_T *)user_service->service,
-+                VCHI_MEM_HANDLE_INVALID,
-+                args.data, args.size,
-+                args.userdata, args.mode,
-+                dir);
-+         } else {
-+            ret = -EINVAL;
-+         }
-+      }
-+      break;
-+
-+   case VCHIQ_IOC_AWAIT_COMPLETION:
-+      {
-+         VCHIQ_AWAIT_COMPLETION_T args;
-+
-+         DEBUG_TRACE(AWAIT_COMPLETION_LINE);
-+         if (!instance->connected) {
-+            ret = -ENOTCONN;
-+            break;
-+         }
-+
-+         if (copy_from_user
-+             (&args, (const void __user *)arg,
-+              sizeof(args)) != 0) {
-+            ret = -EFAULT;
-+            break;
-+         }
-+         DEBUG_TRACE(AWAIT_COMPLETION_LINE);
-+         while ((instance->completion_remove ==
-+            instance->completion_insert)
-+                && !instance->closing) {
-+            DEBUG_TRACE(AWAIT_COMPLETION_LINE);
-+            if (vcos_event_wait(&instance->insert_event) !=
-+                VCOS_SUCCESS) {
-+               DEBUG_TRACE(AWAIT_COMPLETION_LINE);
-+               vcos_log_info
-+                   ("AWAIT_COMPLETION interrupted");
-+               ret = -EINTR;
-+               break;
-+            }
-+         }
-+         DEBUG_TRACE(AWAIT_COMPLETION_LINE);
-+
-+         /* A read memory barrier is needed to stop prefetch of a stale
-+            completion record */
-+         vcos_rmb();
-+
-+         if (ret == 0) {
-+            int msgbufcount = args.msgbufcount;
-+            for (ret = 0; ret < args.count; ret++) {
-+               VCHIQ_COMPLETION_DATA_T *completion;
-+               USER_SERVICE_T *service;
-+               VCHIQ_HEADER_T *header;
-+               if (instance->completion_remove ==
-+                   instance->completion_insert)
-+                  break;
-+               completion =
-+                   &instance->
-+                   completions
-+                   [instance->completion_remove &
-+                    (MAX_COMPLETIONS - 1)];
-+
-+               service = (USER_SERVICE_T *)completion->service_userdata;
-+               completion->service_userdata = service->userdata;
-+
-+               header = completion->header;
-+               if (header)
-+               {
-+                  void __user *msgbuf;
-+                  int msglen;
-+
-+                  msglen = header->size + sizeof(VCHIQ_HEADER_T);
-+                  /* This must be a VCHIQ-style service */
-+                  if (args.msgbufsize < msglen)
-+                  {
-+                     vcos_log_error("header %x: msgbufsize %x < msglen %x",
-+                        (unsigned int)header, args.msgbufsize, msglen);
-+                     vcos_assert(0);
-+                     if (ret == 0)
-+                        ret = -EMSGSIZE;
-+                     break;
-+                  }
-+                  if (msgbufcount <= 0)
-+                  {
-+                     /* Stall here for lack of a buffer for the message */
-+                     break;
-+                  }
-+                  /* Get the pointer from user space */
-+                  msgbufcount--;
-+                  if (copy_from_user(&msgbuf,
-+                     (const void __user *)&args.msgbufs[msgbufcount],
-+                     sizeof(msgbuf)) != 0)
-+                  {
-+                     if (ret == 0)
-+                        ret = -EFAULT;
-+                     break;
-+                  }
-+
-+                  /* Copy the message to user space */
-+                  if (copy_to_user(msgbuf, header, msglen) != 0)
-+                  {
-+                     if (ret == 0)
-+                        ret = -EFAULT;
-+                     break;
-+                  }
-+
-+                  /* Now it has been copied, the message can be released. */
-+                  vchiq_release_message(&service->service->base, header);
-+
-+                  /* The completion must point to the msgbuf */
-+                  completion->header = msgbuf;
-+               }
-+
-+               if (copy_to_user
-+                   ((void __user *)((size_t) args.buf +
-+                          ret *
-+                          sizeof
-+                          (VCHIQ_COMPLETION_DATA_T)),
-+                    completion,
-+                    sizeof(VCHIQ_COMPLETION_DATA_T)) !=
-+                   0) {
-+                  if (ret == 0)
-+                     ret = -EFAULT;
-+                  break;
-+               }
-+               instance->completion_remove++;
-+            }
-+
-+            if (msgbufcount != args.msgbufcount)
-+            {
-+               if (copy_to_user((void __user *)
-+                  &((VCHIQ_AWAIT_COMPLETION_T *)arg)->msgbufcount,
-+                  &msgbufcount, sizeof(msgbufcount)) != 0)
-+               {
-+                  ret = -EFAULT;
-+                  break;
-+               }
-+            }
-+         }
-+
-+         if (ret != 0)
-+            vcos_event_signal(&instance->remove_event);
-+         DEBUG_TRACE(AWAIT_COMPLETION_LINE);
-+      }
-+      break;
-+
-+   case VCHIQ_IOC_DEQUEUE_MESSAGE:
-+      {
-+         VCHIQ_DEQUEUE_MESSAGE_T args;
-+         USER_SERVICE_T *user_service;
-+         VCHIQ_HEADER_T *header;
-+
-+         DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
-+         if (copy_from_user
-+             (&args, (const void __user *)arg,
-+              sizeof(args)) != 0) {
-+            ret = -EFAULT;
-+            break;
-+         }
-+         user_service = &instance->services[args.handle];
-+         if ((args.handle < 0) || (args.handle >= MAX_SERVICES) ||
-+            (user_service->service == NULL) ||
-+            (user_service->is_vchi == 0)) {
-+            ret = -EINVAL;
-+            break;
-+         }
-+         if (user_service->msg_remove == user_service->msg_insert)
-+         {
-+            if (!args.blocking)
-+            {
-+               DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
-+               ret = -EWOULDBLOCK;
-+               break;
-+            }
-+            user_service->dequeue_pending = 1;
-+            do {
-+               DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
-+               if (vcos_event_wait(&user_service->insert_event) !=
-+                   VCOS_SUCCESS) {
-+                  vcos_log_info("DEQUEUE_MESSAGE interrupted");
-+                  ret = -EINTR;
-+                  break;
-+               }
-+            }
-+            while (user_service->msg_remove == user_service->msg_insert);
-+         }
-+
-+         /* A read memory barrier is needed to stop prefetch of a stale
-+            header value */
-+         vcos_rmb();
-+
-+         header = user_service->msg_queue[user_service->msg_remove &
-+            (MSG_QUEUE_SIZE - 1)];
-+         if (header == NULL)
-+            ret = -ENOTCONN;
-+         else if (header->size <= args.bufsize)
-+         {
-+            /* Copy to user space if msgbuf is not NULL */
-+            if ((args.buf == NULL) ||
-+               (copy_to_user((void __user *)args.buf, header->data,
-+               header->size) == 0))
-+            {
-+               ret = header->size;
-+               vchiq_release_message(&user_service->service->base,
-+                  header);
-+               user_service->msg_remove++;
-+               vcos_event_signal(&user_service->remove_event);
-+            }
-+            else
-+               ret = -EFAULT;
-+         }
-+         else
-+         {
-+            vcos_log_error("header %x: bufsize %x < size %x",
-+               (unsigned int)header, args.bufsize, header->size);
-+            vcos_assert(0);
-+            ret = -EMSGSIZE;
-+         }
-+         DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
-+      }
-+      break;
-+
-+   case VCHIQ_IOC_GET_CLIENT_ID:
-+      {
-+         USER_SERVICE_T *user_service;
-+         int handle = (int)arg;
-+
-+         user_service = find_service_by_handle(instance, handle);
-+         if (user_service != NULL)
-+            ret = vchiq_get_client_id(&user_service->service->base);
-+         else
-+            ret = 0;
-+      }
-+      break;
-+
-+   case VCHIQ_IOC_GET_CONFIG:
-+      {
-+         VCHIQ_GET_CONFIG_T args;
-+         VCHIQ_CONFIG_T config;
-+
-+         if (copy_from_user
-+             (&args, (const void __user *)arg,
-+              sizeof(args)) != 0) {
-+            ret = -EFAULT;
-+            break;
-+         }
-+         if (args.config_size > sizeof(config))
-+         {
-+            ret = -EINVAL;
-+            break;
-+         }
-+         status = vchiq_get_config(instance, args.config_size, &config);
-+         if (status == VCHIQ_SUCCESS)
-+         {
-+            if (copy_to_user((void __user *)args.pconfig,
-+                   &config, args.config_size) != 0)
-+            {
-+               ret = -EFAULT;
-+               break;
-+            }
-+         }
-+      }
-+      break;
-+
-+   case VCHIQ_IOC_SET_SERVICE_OPTION:
-+      {
-+         VCHIQ_SET_SERVICE_OPTION_T args;
-+         USER_SERVICE_T *user_service;
-+
-+         if (copy_from_user(
-+            &args, (const void __user *)arg,
-+            sizeof(args)) != 0)
-+         {
-+            ret = -EFAULT;
-+            break;
-+         }
-+
-+         user_service = find_service_by_handle(instance, args.handle);
-+         if (user_service != NULL)
-+         {
-+            status = vchiq_set_service_option(
-+               &user_service->service->base,
-+               args.option, args.value);
-+         }
-+         else
-+         {
-+            ret = -EINVAL;
-+         }
-+      }
-+      break;
-+
-+   default:
-+      ret = -ENOTTY;
-+      break;
-+   }
-+
-+   if (ret == 0) {
-+      if (status == VCHIQ_ERROR)
-+         ret = -EIO;
-+      else if (status == VCHIQ_RETRY)
-+         ret = -EINTR;
-+   }
-+
-+   if ((ret < 0) && (ret != -EINTR) && (ret != -EWOULDBLOCK))
-+      vcos_log_warn("  ioctl instance %lx, cmd %s -> status %d, %ld",
-+         (unsigned long)instance,
-+         (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ? ioctl_names[_IOC_NR(cmd)] :
-+         "<invalid>", status, ret);
-+   else
-+      vcos_log_trace("  ioctl instance %lx, cmd %s -> status %d, %ld",
-+         (unsigned long)instance,
-+         (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ? ioctl_names[_IOC_NR(cmd)] :
-+         "<invalid>", status, ret);
-+
-+   return ret;
-+}
-+
-+/****************************************************************************
-+*
-+*   vchiq_open
-+*
-+***************************************************************************/
-+
-+static int
-+vchiq_open(struct inode *inode, struct file *file)
-+{
-+   int dev = iminor(inode) & 0x0f;
-+   vcos_log_info("vchiq_open");
-+   switch (dev) {
-+   case VCHIQ_MINOR:
-+      {
-+         VCHIQ_STATE_T *state = vchiq_get_state();
-+         VCHIQ_INSTANCE_T instance;
-+
-+         if (!state)
-+         {
-+            vcos_log_error( "vchiq has no connection to VideoCore");
-+            return -ENOTCONN;
-+         }
-+
-+         instance = kzalloc(sizeof(*instance), GFP_KERNEL);
-+         if (!instance)
-+            return -ENOMEM;
-+
-+         instance->state = state;
-+         instance->pid = current->tgid;
-+         vcos_event_create(&instance->insert_event, DEVICE_NAME);
-+         vcos_event_create(&instance->remove_event, DEVICE_NAME);
-+
-+         file->private_data = instance;
-+      }
-+      break;
-+
-+   default:
-+      vcos_log_error("Unknown minor device: %d", dev);
-+      return -ENXIO;
-+   }
-+
-+   return 0;
-+}
-+
-+/****************************************************************************
-+*
-+*   vchiq_release
-+*
-+***************************************************************************/
-+
-+static int
-+vchiq_release(struct inode *inode, struct file *file)
-+{
-+   int dev = iminor(inode) & 0x0f;
-+   int ret = 0;
-+   switch (dev) {
-+   case VCHIQ_MINOR:
-+      {
-+         VCHIQ_INSTANCE_T instance = file->private_data;
-+         int i;
-+
-+         vcos_log_info("vchiq_release: instance=%lx",
-+                  (unsigned long)instance);
-+
-+         instance->closing = 1;
-+
-+         /* Wake the slot handler if the completion queue is full */
-+         vcos_event_signal(&instance->remove_event);
-+
-+         /* Mark all services for termination... */
-+
-+         for (i = 0; i < MAX_SERVICES; i++) {
-+            USER_SERVICE_T *user_service =
-+                &instance->services[i];
-+            if (user_service->service != NULL)
-+            {
-+               /* Wake the slot handler if the msg queue is full */
-+               vcos_event_signal(&user_service->remove_event);
-+
-+               if ((user_service->service->srvstate != VCHIQ_SRVSTATE_CLOSEWAIT) &&
-+                  (user_service->service->srvstate != VCHIQ_SRVSTATE_LISTENING))
-+               {
-+                  vchiq_terminate_service_internal(user_service->service);
-+               }
-+            }
-+         }
-+
-+         /* ...and wait for them to die */
-+
-+         for (i = 0; i < MAX_SERVICES; i++) {
-+            USER_SERVICE_T *user_service =
-+                &instance->services[i];
-+            if (user_service->service != NULL)
-+            {
-+               /* Wait in this non-portable fashion because interruptible
-+                  calls will not block in this context. */
-+               while ((user_service->service->srvstate != VCHIQ_SRVSTATE_CLOSEWAIT) &&
-+                  (user_service->service->srvstate != VCHIQ_SRVSTATE_LISTENING))
-+               {
-+                  down(&user_service->service->remove_event);
-+               }
-+
-+               vchiq_free_service_internal
-+                      (user_service->service);
-+            }
-+         }
-+
-+         vcos_event_delete(&instance->insert_event);
-+         vcos_event_delete(&instance->remove_event);
-+
-+         kfree(instance);
-+         file->private_data = NULL;
-+      }
-+      break;
-+
-+   default:
-+      vcos_log_error("Unknown minor device: %d", dev);
-+      ret = -ENXIO;
-+   }
-+
-+   return ret;
-+}
-+
-+/****************************************************************************
-+*
-+*   vchiq_dump
-+*
-+***************************************************************************/
-+
-+void
-+vchiq_dump(void *dump_context, const char *str, int len)
-+{
-+   DUMP_CONTEXT_T *context = (DUMP_CONTEXT_T *)dump_context;
-+
-+   if ((context->actual >= 0) && (context->actual < context->space))
-+   {
-+      int copy_bytes;
-+      if (context->offset > 0)
-+      {
-+         int skip_bytes = vcos_min(len, context->offset);
-+         str += skip_bytes;
-+         len -= skip_bytes;
-+         context->offset -= skip_bytes;
-+         if (context->offset > 0)
-+            return;
-+      }
-+      copy_bytes = vcos_min(len, context->space - context->actual);
-+      if (copy_bytes == 0)
-+         return;
-+      if (copy_to_user(context->buf + context->actual, str, copy_bytes))
-+         context->actual = -EFAULT;
-+      context->actual += copy_bytes;
-+      len -= copy_bytes;
-+
-+      /* If tne terminating NUL is included in the length, then it marks
-+       * the end of a line and should be replaced with a carriage return.
-+       */
-+      if ((len == 0) && (str[copy_bytes - 1] == '\0'))
-+      {
-+         char cr = '\n';
-+         if (copy_to_user(context->buf + context->actual - 1, &cr, 1))
-+         {
-+          context->actual = -EFAULT;
-+         }
-+      }
-+   }
-+}
-+
-+/****************************************************************************
-+*
-+*   vchiq_dump_platform_instance_state
-+*
-+***************************************************************************/
-+
-+void
-+vchiq_dump_platform_instances(void *dump_context)
-+{
-+   VCHIQ_STATE_T *state = vchiq_get_state();
-+   char buf[80];
-+   int len;
-+   int i;
-+
-+   /* There is no list of instances, so instead scan all services,
-+      marking those that have been dumped. */
-+
-+   for (i = 0; i < state->unused_service; i++)
-+   {
-+      VCHIQ_SERVICE_T *service = state->services[i];
-+      VCHIQ_INSTANCE_T instance;
-+
-+      if (service
-+         && ((instance = service->instance) != NULL)
-+         && (service->base.callback == service_callback))
-+         instance->mark = 0;
-+   }
-+
-+   for (i = 0; i < state->unused_service; i++)
-+   {
-+      VCHIQ_SERVICE_T *service = state->services[i];
-+      VCHIQ_INSTANCE_T instance;
-+
-+      if (service
-+         && ((instance = service->instance) != NULL)
-+         && (service->base.callback == service_callback))
-+      {
-+         if (!instance->mark)
-+         {
-+            len = vcos_snprintf(buf, sizeof(buf),
-+               "Instance %x: pid %d,%s completions %d/%d",
-+               (unsigned int)instance, instance->pid,
-+               instance->connected ? " connected," : "",
-+               instance->completion_insert - instance->completion_remove,
-+               MAX_COMPLETIONS);
-+
-+            vchiq_dump(dump_context, buf, len + 1);
-+
-+            instance->mark = 1;
-+         }
-+      }
-+   }
-+}
-+
-+/****************************************************************************
-+*
-+*   vchiq_dump_platform_service_state
-+*
-+***************************************************************************/
-+
-+void
-+vchiq_dump_platform_service_state(void *dump_context, VCHIQ_SERVICE_T *service)
-+{
-+   USER_SERVICE_T *user_service = (USER_SERVICE_T *)service->base.userdata;
-+   char buf[80];
-+   int len;
-+
-+   len = vcos_snprintf(buf, sizeof(buf), "  instance %x",
-+      service->instance);
-+
-+   if ((service->base.callback == service_callback) && user_service->is_vchi)
-+   {
-+      len += vcos_snprintf(buf + len, sizeof(buf) - len,
-+         ", %d/%d messages",
-+         user_service->msg_insert - user_service->msg_remove,
-+         MSG_QUEUE_SIZE);
-+
-+      if (user_service->dequeue_pending)
-+         len += vcos_snprintf(buf + len, sizeof(buf) - len,
-+            " (dequeue pending)");
-+   }
-+
-+   vchiq_dump(dump_context, buf, len + 1);
-+}
-+
-+/****************************************************************************
-+*
-+*   vchiq_read
-+*
-+***************************************************************************/
-+
-+static ssize_t
-+vchiq_read(struct file * file, char __user * buf,
-+   size_t count, loff_t *ppos)
-+{
-+   DUMP_CONTEXT_T context;
-+   context.buf = buf;
-+   context.actual = 0;
-+   context.space = count;
-+   context.offset = *ppos;
-+
-+   vchiq_dump_state(&context, &g_state);
-+
-+   if (context.actual >= 0)
-+      *ppos += context.actual;
-+
-+   return context.actual;
-+}
-+
-+VCHIQ_STATE_T *
-+vchiq_get_state(void)
-+{
-+
-+   if (g_state.remote == NULL)
-+   {
-+      printk( "%s: g_state.remote == NULL\n", __func__ );
-+   }
-+   else
-+   {
-+      if ( g_state.remote->initialised != 1)
-+      {
-+         printk( "%s: g_state.remote->initialised != 1 (%d)\n", __func__, g_state.remote->initialised );
-+      }
-+   }
-+
-+   return ((g_state.remote != NULL) &&
-+      (g_state.remote->initialised == 1)) ? &g_state : NULL;
-+}
-+
-+static const struct file_operations
-+vchiq_fops = {
-+   .owner = THIS_MODULE,
-+   .unlocked_ioctl = vchiq_ioctl,
-+   .open = vchiq_open,
-+   .release = vchiq_release,
-+   .read = vchiq_read
-+};
-+
-+/****************************************************************************
-+*
-+*   vchiq_init - called when the module is loaded.
-+*
-+***************************************************************************/
-+
-+static int __init
-+vchiq_init(void)
-+{
-+   int err;
-+   void *ptr_err;
-+
-+   err = vchiq_platform_vcos_init();
-+   if (err != 0)
-+      goto failed_platform_vcos_init;
-+
-+   vcos_log_set_level(VCOS_LOG_CATEGORY, vchiq_default_arm_log_level);
-+   vcos_log_register("vchiq_arm", VCOS_LOG_CATEGORY);
-+
-+   if ((err =
-+        alloc_chrdev_region(&vchiq_devid, VCHIQ_MINOR, 1,
-+             DEVICE_NAME)) != 0) {
-+      vcos_log_error("Unable to allocate device number");
-+      goto failed_alloc_chrdev;
-+   }
-+   cdev_init(&vchiq_cdev, &vchiq_fops);
-+   vchiq_cdev.owner = THIS_MODULE;
-+   if ((err = cdev_add(&vchiq_cdev, vchiq_devid, 1)) != 0) {
-+      vcos_log_error("Unable to register device");
-+      goto failed_cdev_add;
-+   }
-+
-+   /* create sysfs entries */
-+   vchiq_class = class_create(THIS_MODULE, DEVICE_NAME);
-+   if (IS_ERR(ptr_err = vchiq_class))
-+      goto failed_class_create;
-+
-+   vchiq_dev = device_create(vchiq_class, NULL,
-+      vchiq_devid, NULL, "vchiq");
-+   if (IS_ERR(ptr_err = vchiq_dev))
-+      goto failed_device_create;
-+
-+   err = vchiq_platform_init(&g_state);
-+   if (err != 0)
-+      goto failed_platform_init;
-+
-+   vcos_log_error("vchiq: initialised - version %d (min %d), device %d.%d",
-+      VCHIQ_VERSION, VCHIQ_VERSION_MIN,
-+      MAJOR(vchiq_devid), MINOR(vchiq_devid));
-+
-+   return 0;
-+
-+failed_platform_init:
-+   device_destroy(vchiq_class, vchiq_devid);
-+failed_device_create:
-+   class_destroy(vchiq_class);
-+failed_class_create:
-+   cdev_del(&vchiq_cdev);
-+   err = PTR_ERR(ptr_err);
-+failed_cdev_add:
-+   unregister_chrdev_region(vchiq_devid, 1);
-+failed_alloc_chrdev:
-+failed_platform_vcos_init:
-+   printk(KERN_WARNING "could not load vchiq\n");
-+   return err;
-+}
-+/****************************************************************************
-+*
-+*   vchiq_exit - called when the module is unloaded.
-+*
-+***************************************************************************/
-+
-+static void __exit
-+vchiq_exit(void)
-+{
-+   vchiq_platform_exit(&g_state);
-+   device_destroy(vchiq_class, vchiq_devid);
-+   class_destroy(vchiq_class);
-+   cdev_del(&vchiq_cdev);
-+   unregister_chrdev_region(vchiq_devid, 1);
-+   vcos_log_unregister(VCOS_LOG_CATEGORY);
-+}
-+
-+module_init(vchiq_init);
-+module_exit(vchiq_exit);
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Broadcom Corporation");
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h
-@@ -0,0 +1,38 @@
-+/*
-+ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#ifndef VCHIQ_ARM_H
-+#define VCHIQ_ARM_H
-+
-+#include "vchiq_core.h"
-+
-+extern VCOS_LOG_CAT_T vchiq_arm_log_category;
-+
-+extern int __init
-+vchiq_platform_vcos_init(void);
-+
-+extern int __init
-+vchiq_platform_init(VCHIQ_STATE_T *state);
-+
-+extern void __exit
-+vchiq_platform_exit(VCHIQ_STATE_T *state);
-+
-+extern VCHIQ_STATE_T *
-+vchiq_get_state(void);
-+
-+#endif /* VCHIQ_ARM_H */
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h
-@@ -0,0 +1,43 @@
-+/*
-+ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#ifndef VCHIQ_CFG_H
-+#define VCHIQ_CFG_H
-+
-+#define VCHIQ_MAGIC              VCHIQ_MAKE_FOURCC('V','C','H','I')
-+/* The version of VCHIQ - change with any non-trivial change */
-+#define VCHIQ_VERSION            2
-+/* The minimum compatible version - update to match VCHIQ_VERSION with any incompatible change */
-+#define VCHIQ_VERSION_MIN        2
-+
-+#define VCHIQ_MAX_SERVICES       4096
-+#define VCHIQ_MAX_SLOTS          128
-+#define VCHIQ_MAX_SLOTS_PER_SIDE 64
-+
-+#define VCHIQ_NUM_CURRENT_BULKS        32
-+#define VCHIQ_NUM_SERVICE_BULKS        4
-+
-+#ifndef VCHIQ_ENABLE_DEBUG
-+#define VCHIQ_ENABLE_DEBUG             1
-+#endif
-+
-+#ifndef VCHIQ_ENABLE_STATS
-+#define VCHIQ_ENABLE_STATS             1
-+#endif
-+
-+#endif /* VCHIQ_CFG_H */
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c
-@@ -0,0 +1,101 @@
-+/*****************************************************************************
-+* Copyright 2001 - 2010 Broadcom Corporation.  All rights reserved.
-+*
-+* Unless you and Broadcom execute a separate written software license
-+* agreement governing use of this software, this software is licensed to you
-+* under the terms of the GNU General Public License version 2, available at
-+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-+*
-+* Notwithstanding the above, under no circumstances may you combine this
-+* software in any way with any other Broadcom software provided under a
-+* license other than the GPL, without Broadcom's express prior written
-+* consent.
-+*****************************************************************************/
-+
-+#include "vcos.h"
-+#include "vchiq_connected.h"
-+#include <linux/module.h>
-+
-+#define  MAX_CALLBACKS  10
-+
-+static   int                        g_connected = 0;
-+static   int                        g_num_deferred_callbacks;
-+static   VCHIQ_CONNECTED_CALLBACK_T g_deferred_callback[ MAX_CALLBACKS ];
-+static   VCOS_ONCE_T                g_once_init;
-+static   VCOS_MUTEX_T               g_connected_mutex;
-+
-+extern VCOS_LOG_CAT_T vchiq_core_log_category;
-+#define  VCOS_LOG_CATEGORY (&vchiq_core_log_category)
-+
-+/****************************************************************************
-+*
-+* Function to initialize our lock.
-+*
-+***************************************************************************/
-+
-+static void connected_init( void )
-+{
-+   vcos_mutex_create( &g_connected_mutex, "connected_mutex");
-+}
-+
-+/****************************************************************************
-+*
-+* This function is used to defer initialization until the vchiq stack is
-+* initialized. If the stack is already initialized, then the callback will
-+* be made immediately, otherwise it will be deferred until
-+* vchiq_call_connected_callbacks is called.
-+*
-+***************************************************************************/
-+
-+void vchiq_add_connected_callback( VCHIQ_CONNECTED_CALLBACK_T callback )
-+{
-+   vcos_once( &g_once_init, connected_init );
-+
-+   vcos_mutex_lock( &g_connected_mutex );
-+
-+   if ( g_connected )
-+   {
-+      // We're already connected. Call the callback immediately.
-+
-+      callback();
-+   }
-+   else
-+   {
-+      if ( g_num_deferred_callbacks >= MAX_CALLBACKS )
-+      {
-+         vcos_log_error( "There already %d callback registered - please increase MAX_CALLBACKS",
-+                         g_num_deferred_callbacks );
-+      }
-+      else
-+      {
-+         g_deferred_callback[ g_num_deferred_callbacks ] = callback;
-+         g_num_deferred_callbacks++;
-+      }
-+   }
-+   vcos_mutex_unlock( &g_connected_mutex );
-+}
-+
-+/****************************************************************************
-+*
-+* This function is called by the vchiq stack once it has been connected to
-+* the videocore and clients can start to use the stack.
-+*
-+***************************************************************************/
-+
-+void vchiq_call_connected_callbacks( void )
-+{
-+   int   i;
-+
-+   vcos_once( &g_once_init, connected_init );
-+
-+   vcos_mutex_lock( &g_connected_mutex );
-+   for ( i = 0; i <  g_num_deferred_callbacks; i++ )\
-+   {
-+      g_deferred_callback[i]();
-+   }
-+   g_num_deferred_callbacks = 0;
-+   g_connected = 1;
-+   vcos_mutex_unlock( &g_connected_mutex );
-+}
-+
-+EXPORT_SYMBOL( vchiq_add_connected_callback );
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h
-@@ -0,0 +1,32 @@
-+/*****************************************************************************
-+* Copyright 2001 - 2010 Broadcom Corporation.  All rights reserved.
-+*
-+* Unless you and Broadcom execute a separate written software license
-+* agreement governing use of this software, this software is licensed to you
-+* under the terms of the GNU General Public License version 2, available at
-+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-+*
-+* Notwithstanding the above, under no circumstances may you combine this
-+* software in any way with any other Broadcom software provided under a
-+* license other than the GPL, without Broadcom's express prior written
-+* consent.
-+*****************************************************************************/
-+
-+#ifndef VCHIQ_CONNECTED_H
-+#define VCHIQ_CONNECTED_H
-+
-+/* ---- Include Files ----------------------------------------------------- */
-+
-+/* ---- Constants and Types ---------------------------------------------- */
-+
-+typedef void (*VCHIQ_CONNECTED_CALLBACK_T)( void );
-+
-+/* ---- Variable Externs ------------------------------------------------- */
-+
-+/* ---- Function Prototypes ---------------------------------------------- */
-+
-+void vchiq_add_connected_callback( VCHIQ_CONNECTED_CALLBACK_T callback );
-+void vchiq_call_connected_callbacks( void );
-+
-+#endif /* VCHIQ_CONNECTED_H */
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c
-@@ -0,0 +1,2604 @@
-+/*
-+ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#include "vchiq_core.h"
-+
-+#define VCHIQ_SLOT_HANDLER_STACK 8192
-+
-+#define SLOT_INFO_FROM_INDEX(state, index) (state->slot_info + (index))
-+#define SLOT_DATA_FROM_INDEX(state, index) (state->slot_data + (index))
-+#define SLOT_INDEX_FROM_DATA(state, data) (((unsigned int)((char *)data - (char *)state->slot_data)) / VCHIQ_SLOT_SIZE)
-+#define SLOT_INDEX_FROM_INFO(state, info) ((unsigned int)(info - state->slot_info))
-+#define SLOT_QUEUE_INDEX_FROM_POS(pos) ((int)((unsigned int)(pos) / VCHIQ_SLOT_SIZE))
-+
-+#define VCOS_LOG_CATEGORY (&vchiq_core_log_category)
-+
-+#define BULK_INDEX(x) (x & (VCHIQ_NUM_SERVICE_BULKS - 1))
-+
-+typedef struct bulk_waiter_struct
-+{
-+   VCOS_EVENT_T event;
-+   int actual;
-+} BULK_WAITER_T;
-+
-+typedef struct vchiq_open_payload_struct{
-+   int fourcc;
-+   int client_id;
-+   short version;
-+   short version_min;
-+} VCHIQ_OPEN_PAYLOAD_T;
-+
-+vcos_static_assert(sizeof(VCHIQ_HEADER_T) == 8);   /* we require this for consistency between endpoints */
-+vcos_static_assert(IS_POW2(sizeof(VCHIQ_HEADER_T)));
-+vcos_static_assert(IS_POW2(VCHIQ_NUM_CURRENT_BULKS));
-+vcos_static_assert(IS_POW2(VCHIQ_NUM_SERVICE_BULKS));
-+
-+VCOS_LOG_CAT_T vchiq_core_log_category;
-+VCOS_LOG_CAT_T vchiq_core_msg_log_category;
-+VCOS_LOG_LEVEL_T vchiq_default_core_log_level = VCOS_LOG_WARN;
-+VCOS_LOG_LEVEL_T vchiq_default_core_msg_log_level = VCOS_LOG_WARN;
-+
-+static const char *const srvstate_names[] =
-+{
-+   "FREE",
-+   "HIDDEN",
-+   "LISTENING",
-+   "OPENING",
-+   "OPEN",
-+   "CLOSESENT",
-+   "CLOSING",
-+   "CLOSEWAIT"
-+};
-+
-+static const char *const reason_names[] =
-+{
-+   "SERVICE_OPENED",
-+   "SERVICE_CLOSED",
-+   "MESSAGE_AVAILABLE",
-+   "BULK_TRANSMIT_DONE",
-+   "BULK_RECEIVE_DONE",
-+   "BULK_TRANSMIT_ABORTED",
-+   "BULK_RECEIVE_ABORTED"
-+};
-+
-+static const char *const conn_state_names[] =
-+{
-+   "DISCONNECTED",
-+   "CONNECTED",
-+   "PAUSING",
-+   "PAUSE_SENT",
-+   "PAUSED",
-+   "RESUMING"
-+};
-+
-+static const char *msg_type_str( unsigned int msg_type )
-+{
-+   switch (msg_type) {
-+   case VCHIQ_MSG_PADDING:       return "PADDING";
-+   case VCHIQ_MSG_CONNECT:       return "CONNECT";
-+   case VCHIQ_MSG_OPEN:          return "OPEN";
-+   case VCHIQ_MSG_OPENACK:       return "OPENACK";
-+   case VCHIQ_MSG_CLOSE:         return "CLOSE";
-+   case VCHIQ_MSG_DATA:          return "DATA";
-+   case VCHIQ_MSG_BULK_RX:       return "BULK_RX";
-+   case VCHIQ_MSG_BULK_TX:       return "BULK_TX";
-+   case VCHIQ_MSG_BULK_RX_DONE:  return "BULK_RX_DONE";
-+   case VCHIQ_MSG_BULK_TX_DONE:  return "BULK_TX_DONE";
-+   case VCHIQ_MSG_PAUSE:         return "PAUSE";
-+   case VCHIQ_MSG_RESUME:        return "RESUME";
-+   }
-+   return "???";
-+}
-+
-+static inline void
-+vchiq_set_service_state(VCHIQ_SERVICE_T *service, int newstate)
-+{
-+   vcos_log_info("%d: srv:%d %s->%s", service->state->id, service->localport,
-+      srvstate_names[service->srvstate],
-+      srvstate_names[newstate]);
-+   service->srvstate = newstate;
-+}
-+
-+static inline VCHIQ_STATUS_T
-+make_service_callback(VCHIQ_SERVICE_T *service, VCHIQ_REASON_T reason,
-+   VCHIQ_HEADER_T *header, void *bulk_userdata)
-+{
-+   vcos_log_trace("%d: callback:%d (%s, %x, %x)", service->state->id,
-+      service->localport, reason_names[reason],
-+      (unsigned int)header, (unsigned int)bulk_userdata);
-+   return service->base.callback(reason, header, &service->base, bulk_userdata);
-+}
-+
-+static inline void
-+vchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate)
-+{
-+   vcos_log_info("%d: %s->%s", state->id,
-+      conn_state_names[state->conn_state],
-+      conn_state_names[newstate]);
-+   state->conn_state = newstate;
-+}
-+
-+static inline void
-+remote_event_create(REMOTE_EVENT_T *event)
-+{
-+   event->armed = 0;
-+   /* Don't clear the 'fired' flag because it may already have been set by the other side */
-+   vcos_event_create(event->event, "vchiq");
-+}
-+
-+static inline void
-+remote_event_destroy(REMOTE_EVENT_T *event)
-+{
-+   vcos_event_delete(event->event);
-+}
-+
-+static inline int
-+remote_event_wait(REMOTE_EVENT_T *event)
-+{
-+   if (!event->fired)
-+   {
-+      event->armed = 1;
-+      if (event->fired) /* Also ensures the write has completed */
-+         event->armed = 0;
-+      else if (vcos_event_wait(event->event) != VCOS_SUCCESS)
-+         return 0;
-+   }
-+
-+   event->fired = 0;
-+   return 1;
-+}
-+
-+static inline void
-+remote_event_signal_local(REMOTE_EVENT_T *event)
-+{
-+   event->armed = 0;
-+   vcos_event_signal(event->event);
-+}
-+
-+static inline void
-+remote_event_poll(REMOTE_EVENT_T *event)
-+{
-+   if (event->armed)
-+      remote_event_signal_local(event);
-+}
-+
-+void
-+remote_event_pollall(VCHIQ_STATE_T *state)
-+{
-+   remote_event_poll(&state->local->trigger);
-+   remote_event_poll(&state->local->recycle);
-+}
-+
-+/* Round up message sizes so that any space at the end of a slot is always big
-+   enough for a header. This relies on header size being a power of two, which
-+   has been verified earlier by a static assertion. */
-+
-+static inline unsigned int
-+calc_stride(unsigned int size)
-+{
-+   /* Allow room for the header */
-+   size += sizeof(VCHIQ_HEADER_T);
-+
-+   /* Round up */
-+   return (size + sizeof(VCHIQ_HEADER_T) - 1) & ~(sizeof(VCHIQ_HEADER_T) - 1);
-+}
-+
-+static VCHIQ_SERVICE_T *
-+get_listening_service(VCHIQ_STATE_T *state, int fourcc)
-+{
-+   int i;
-+
-+   vcos_assert(fourcc != VCHIQ_FOURCC_INVALID);
-+
-+   for (i = 0; i < state->unused_service; i++)
-+   {
-+      VCHIQ_SERVICE_T *service = state->services[i];
-+      if (service &&
-+         (service->public_fourcc == fourcc) &&
-+         ((service->srvstate == VCHIQ_SRVSTATE_LISTENING) ||
-+         ((service->srvstate == VCHIQ_SRVSTATE_OPEN) &&
-+         (service->remoteport == VCHIQ_PORT_FREE))))
-+         return service;
-+   }
-+
-+   return NULL;
-+}
-+
-+static VCHIQ_SERVICE_T *
-+get_connected_service(VCHIQ_STATE_T *state, unsigned int port)
-+{
-+   int i;
-+   for (i = 0; i < state->unused_service; i++) {
-+      VCHIQ_SERVICE_T *service = state->services[i];
-+      if (service && (service->srvstate == VCHIQ_SRVSTATE_OPEN)
-+         && (service->remoteport == port)) {
-+         return service;
-+      }
-+   }
-+   return NULL;
-+}
-+
-+static inline void
-+request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type)
-+{
-+   if (service)
-+   {
-+      vcos_atomic_flags_or(&service->poll_flags, (1 << poll_type));
-+      vcos_atomic_flags_or(&state->poll_services[service->localport>>5],
-+         (1 <<(service->localport & 0x1f)));
-+   }
-+
-+   state->poll_needed = 1;
-+   vcos_wmb(&state->poll_needed);
-+
-+   /* ... and ensure the slot handler runs. */
-+   remote_event_signal_local(&state->local->trigger);
-+}
-+
-+/* Called from queue_message, by the slot handler and application threads,
-+   with slot_mutex held */
-+static VCHIQ_HEADER_T *
-+reserve_space(VCHIQ_STATE_T *state, int space, int is_blocking)
-+{
-+   VCHIQ_SHARED_STATE_T *local = state->local;
-+   int tx_pos = state->local_tx_pos;
-+   int slot_space = VCHIQ_SLOT_SIZE - (tx_pos & VCHIQ_SLOT_MASK);
-+
-+   if (space > slot_space) {
-+      VCHIQ_HEADER_T *header;
-+      /* Fill the remaining space with padding */
-+      vcos_assert(state->tx_data != NULL);
-+      header = (VCHIQ_HEADER_T *) (state->tx_data + (tx_pos & VCHIQ_SLOT_MASK));
-+      header->msgid = VCHIQ_MSGID_PADDING;
-+      header->size = slot_space - sizeof(VCHIQ_HEADER_T);
-+
-+      tx_pos += slot_space;
-+   }
-+
-+   /* If necessary, get the next slot. */
-+   if ((tx_pos & VCHIQ_SLOT_MASK) == 0)
-+   {
-+      int slot_index;
-+
-+      /* If there is no free slot... */
-+      if (tx_pos == (state->slot_queue_available * VCHIQ_SLOT_SIZE))
-+      {
-+         /* ...wait for one. */
-+         VCHIQ_STATS_INC(state, slot_stalls);
-+
-+         /* But first, flush through the last slot. */
-+         local->tx_pos = tx_pos;
-+         remote_event_signal(&state->remote->trigger);
-+
-+         do {
-+            if (!is_blocking ||
-+               (vcos_event_wait(&state->slot_available_event) != VCOS_SUCCESS))
-+            {
-+               return NULL; /* No space available now */
-+            }
-+         }
-+         while (tx_pos == (state->slot_queue_available * VCHIQ_SLOT_SIZE));
-+      }
-+
-+      slot_index = local->slot_queue[SLOT_QUEUE_INDEX_FROM_POS(tx_pos) & VCHIQ_SLOT_QUEUE_MASK];
-+      state->tx_data = (char *)SLOT_DATA_FROM_INDEX(state, slot_index);
-+   }
-+
-+   state->local_tx_pos = tx_pos + space;
-+
-+   return (VCHIQ_HEADER_T *)(state->tx_data + (tx_pos & VCHIQ_SLOT_MASK));
-+}
-+
-+/* Called with slot_mutex held */
-+static void
-+process_free_queue(VCHIQ_STATE_T *state)
-+{
-+   VCHIQ_SHARED_STATE_T *local = state->local;
-+   BITSET_T service_found[BITSET_SIZE(VCHIQ_MAX_SERVICES)];
-+   int slot_queue_available;
-+
-+   /* Use a read memory barrier to ensure that any state that may have
-+      been modified by another thread is not masked by stale prefetched
-+      values. */
-+   vcos_rmb();
-+
-+   /* Find slots which have been freed by the other side, and return them to
-+      the available queue. */
-+   slot_queue_available = state->slot_queue_available;
-+
-+   while (slot_queue_available != local->slot_queue_recycle)
-+   {
-+      int pos;
-+      int slot_index = local->slot_queue[slot_queue_available++ & VCHIQ_SLOT_QUEUE_MASK];
-+      char *data = (char *)SLOT_DATA_FROM_INDEX(state, slot_index);
-+
-+      vcos_log_trace("%d: pfq %d=%x %x %x", state->id, slot_index,
-+         (unsigned int)data, local->slot_queue_recycle,
-+         slot_queue_available);
-+
-+      /* Initialise the bitmask for services which have used this slot */
-+      BITSET_ZERO(service_found);
-+
-+      pos = 0;
-+
-+      while (pos < VCHIQ_SLOT_SIZE)
-+      {
-+         VCHIQ_HEADER_T *header = (VCHIQ_HEADER_T *)(data + pos);
-+         int msgid = header->msgid;
-+         if (VCHIQ_MSG_TYPE(msgid) == VCHIQ_MSG_DATA)
-+         {
-+            int port = VCHIQ_MSG_SRCPORT(msgid);
-+            if (!BITSET_IS_SET(service_found, port))
-+            {
-+               VCHIQ_SERVICE_QUOTA_T *service_quota =
-+                  &state->service_quotas[port];
-+
-+               /* Set the found bit for this service */
-+               BITSET_SET(service_found, port);
-+
-+               if (service_quota->slot_use_count > 0)
-+               {
-+                  service_quota->slot_use_count--;
-+                  /* Signal the service in case it has dropped below its quota */
-+                  vcos_event_signal(&service_quota->quota_event);
-+                  vcos_log_trace("%d: pfq:%d %x@%x - slot_use->%d",
-+                     state->id, port,
-+                     header->size, (unsigned int)header,
-+                     service_quota->slot_use_count);
-+               }
-+               else
-+               {
-+                  vcos_log_error("service %d slot_use_count=%d (header %x,"
-+                                 " msgid %x, header->msgid %x, header->size %x)",
-+                     port, service_quota->slot_use_count,
-+                     (unsigned int)header, msgid, header->msgid,
-+                     header->size);
-+                  vcos_assert(0);
-+               }
-+            }
-+         }
-+
-+         pos += calc_stride(header->size);
-+         if (pos > VCHIQ_SLOT_SIZE)
-+         {
-+            vcos_log_error("pos %x: header %x, msgid %x, header->msgid %x, header->size %x",
-+               pos, (unsigned int)header, msgid, header->msgid, header->size);
-+            vcos_assert(0);
-+         }
-+      }
-+   }
-+
-+   if (slot_queue_available != state->slot_queue_available)
-+   {
-+      state->slot_queue_available = slot_queue_available;
-+      vcos_wmb(&state->slot_queue_available);
-+      vcos_event_signal(&state->slot_available_event);
-+   }
-+}
-+
-+/* Called by the slot handler and application threads */
-+static VCHIQ_STATUS_T
-+queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
-+   int msgid, const VCHIQ_ELEMENT_T *elements,
-+   int count, int size, int is_blocking)
-+{
-+   VCHIQ_SHARED_STATE_T *local;
-+   VCHIQ_SERVICE_QUOTA_T *service_quota = NULL;
-+   VCHIQ_HEADER_T *header;
-+
-+   unsigned int stride;
-+
-+   local = state->local;
-+
-+   stride = calc_stride(size);
-+
-+   vcos_assert(stride <= VCHIQ_SLOT_SIZE);
-+
-+   /* On platforms where vcos_mutex_lock cannot fail, the return will never
-+      be taken and the compiler may optimise out that code. Let Coverity
-+      know this is intentional.
-+   */
-+   /* coverity[constant_expression_result] */
-+   if ((VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_RESUME) &&
-+      (vcos_mutex_lock(&state->slot_mutex) != VCOS_SUCCESS))
-+      return VCHIQ_RETRY;
-+
-+   if (service)
-+   {
-+      int tx_end_index = SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos + stride - 1);
-+
-+      if (service->srvstate != VCHIQ_SRVSTATE_OPEN)
-+      {
-+         /* The service has been closed, probably while waiting for the mutex */
-+         vcos_mutex_unlock(&state->slot_mutex);
-+         return VCHIQ_ERROR;
-+      }
-+
-+      service_quota = &state->service_quotas[service->localport];
-+
-+      /* ...ensure it doesn't use more than its quota of slots */
-+      while ((tx_end_index != service_quota->previous_tx_index) &&
-+         (service_quota->slot_use_count == service_quota->slot_quota))
-+      {
-+         vcos_log_trace("%d: qm:%d %s,%x - quota stall",
-+            state->id, service->localport,
-+            msg_type_str(VCHIQ_MSG_TYPE(msgid)), size);
-+         VCHIQ_SERVICE_STATS_INC(service, quota_stalls);
-+         vcos_mutex_unlock(&state->slot_mutex);
-+         if (vcos_event_wait(&service_quota->quota_event) != VCOS_SUCCESS)
-+            return VCHIQ_RETRY;
-+         if (vcos_mutex_lock(&state->slot_mutex) != VCOS_SUCCESS)
-+            return VCHIQ_RETRY;
-+         vcos_assert(service_quota->slot_use_count <= service_quota->slot_quota);
-+         tx_end_index = SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos + stride - 1);
-+      }
-+   }
-+
-+   header = reserve_space(state, stride, is_blocking);
-+
-+   if (!header) {
-+      if (service)
-+         VCHIQ_SERVICE_STATS_INC(service, slot_stalls);
-+      vcos_mutex_unlock(&state->slot_mutex);
-+      return VCHIQ_RETRY;
-+   }
-+
-+   if (service) {
-+      int i, pos;
-+      int tx_end_index;
-+
-+      vcos_log_info("%d: qm %s@%x,%x (%d->%d)", state->id,
-+         msg_type_str(VCHIQ_MSG_TYPE(msgid)),
-+         (unsigned int)header, size,
-+         VCHIQ_MSG_SRCPORT(msgid),
-+         VCHIQ_MSG_DSTPORT(msgid));
-+
-+      for (i = 0, pos = 0; i < (unsigned int)count;
-+         pos += elements[i++].size)
-+         if (elements[i].size) {
-+            if (vchiq_copy_from_user
-+               (header->data + pos, elements[i].data,
-+               (size_t) elements[i].size) !=
-+               VCHIQ_SUCCESS) {
-+               vcos_mutex_unlock(&state->slot_mutex);
-+               VCHIQ_SERVICE_STATS_INC(service, error_count);
-+               return VCHIQ_ERROR;
-+            }
-+            if (i == 0) {
-+               vcos_log_dump_mem( &vchiq_core_msg_log_category,
-+                              "Sent", 0, header->data + pos,
-+                              vcos_min( 64, elements[0].size ));
-+            }
-+         }
-+
-+      /* If this transmission can't fit in the last slot used by this service... */
-+      tx_end_index = SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos - 1);
-+      if (tx_end_index != service_quota->previous_tx_index)
-+      {
-+         service_quota->slot_use_count++;
-+         vcos_log_trace("%d: qm:%d %s,%x - slot_use->%d",
-+            state->id, service->localport,
-+            msg_type_str(VCHIQ_MSG_TYPE(msgid)), size,
-+            service_quota->slot_use_count);
-+      }
-+
-+      service_quota->previous_tx_index = tx_end_index;
-+      VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count);
-+      VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size);
-+   } else {
-+      vcos_log_info("%d: qm %s@%x,%x (%d->%d)", state->id,
-+         msg_type_str(VCHIQ_MSG_TYPE(msgid)),
-+         (unsigned int)header, size,
-+         VCHIQ_MSG_SRCPORT(msgid),
-+         VCHIQ_MSG_DSTPORT(msgid));
-+      if (size != 0)
-+      { 
-+         vcos_assert((count == 1) && (size == elements[0].size));
-+         memcpy(header->data, elements[0].data, elements[0].size);
-+      }
-+      VCHIQ_STATS_INC(state, ctrl_tx_count);
-+   }
-+
-+   header->msgid = msgid;
-+   header->size = size;
-+
-+   if (vcos_is_log_enabled( &vchiq_core_msg_log_category, VCOS_LOG_INFO))
-+   {
-+      int svc_fourcc;
-+
-+      svc_fourcc = service
-+         ? service->base.fourcc
-+         : VCHIQ_MAKE_FOURCC('?','?','?','?');
-+
-+      vcos_log_impl( &vchiq_core_msg_log_category,
-+         VCOS_LOG_INFO,
-+         "Sent Msg %s(%u) to %c%c%c%c s:%u d:%d len:%d",
-+         msg_type_str(VCHIQ_MSG_TYPE(msgid)),
-+         VCHIQ_MSG_TYPE(msgid),
-+         VCHIQ_FOURCC_AS_4CHARS(svc_fourcc),
-+         VCHIQ_MSG_SRCPORT(msgid),
-+         VCHIQ_MSG_DSTPORT(msgid),
-+         size );
-+   }
-+
-+   /* Make the new tx_pos visible to the peer. */
-+   local->tx_pos = state->local_tx_pos;
-+   vcos_wmb(&local->tx_pos);
-+
-+   if (VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_PAUSE)
-+      vcos_mutex_unlock(&state->slot_mutex);
-+
-+   remote_event_signal(&state->remote->trigger);
-+
-+   return VCHIQ_SUCCESS;
-+}
-+
-+static inline void
-+claim_slot(VCHIQ_SLOT_INFO_T *slot)
-+{
-+   slot->use_count++;
-+}
-+
-+static void
-+release_slot(VCHIQ_STATE_T *state, VCHIQ_SLOT_INFO_T *slot_info)
-+{
-+   int release_count;
-+   vcos_mutex_lock(&state->recycle_mutex);
-+
-+   release_count = slot_info->release_count;
-+   slot_info->release_count = ++release_count;
-+
-+   if (release_count == slot_info->use_count)
-+   {
-+      int slot_queue_recycle;
-+      /* Add to the freed queue */
-+
-+      /* A read barrier is necessary here to prevent speculative fetches of
-+         remote->slot_queue_recycle from overtaking the mutex. */
-+      vcos_rmb();
-+
-+      slot_queue_recycle = state->remote->slot_queue_recycle;
-+      state->remote->slot_queue[slot_queue_recycle & VCHIQ_SLOT_QUEUE_MASK] =
-+         SLOT_INDEX_FROM_INFO(state, slot_info);
-+      state->remote->slot_queue_recycle = slot_queue_recycle + 1;
-+      vcos_log_info("%d: release_slot %d - recycle->%x",
-+         state->id, SLOT_INDEX_FROM_INFO(state, slot_info),
-+         state->remote->slot_queue_recycle);
-+
-+      /* A write barrier is necessary, but remote_event_signal contains one. */
-+      remote_event_signal(&state->remote->recycle);
-+   }
-+
-+   vcos_mutex_unlock(&state->recycle_mutex);
-+}
-+
-+/* Called by the slot handler - don't hold the bulk mutex */
-+static VCHIQ_STATUS_T
-+notify_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue)
-+{
-+   VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
-+
-+   vcos_log_trace("%d: nb:%d %cx - p=%x rn=%x r=%x",
-+      service->state->id, service->localport,
-+      (queue == &service->bulk_tx) ? 't' : 'r',
-+      queue->process, queue->remote_notify, queue->remove);
-+
-+   if (service->state->is_master)
-+   {
-+      while (queue->remote_notify != queue->process)
-+      {
-+         VCHIQ_BULK_T *bulk = &queue->bulks[BULK_INDEX(queue->remote_notify)];
-+         int msgtype = (bulk->dir == VCHIQ_BULK_TRANSMIT) ?
-+            VCHIQ_MSG_BULK_RX_DONE : VCHIQ_MSG_BULK_TX_DONE;
-+         int msgid = VCHIQ_MAKE_MSG(msgtype, service->localport, service->remoteport);
-+         VCHIQ_ELEMENT_T element = { &bulk->actual, 4 };
-+         /* Only reply to non-dummy bulk requests */
-+         if (bulk->remote_data)
-+         {
-+            status = queue_message(service->state, NULL, msgid, &element, 1, 4, 0);
-+            if (status != VCHIQ_SUCCESS)
-+               break;
-+         }
-+         queue->remote_notify++;
-+      }
-+   }
-+   else
-+   {
-+      queue->remote_notify = queue->process;
-+   }
-+
-+   if (status == VCHIQ_SUCCESS)
-+   {
-+      while (queue->remove != queue->remote_notify)
-+      {
-+         VCHIQ_BULK_T *bulk = &queue->bulks[BULK_INDEX(queue->remove)];
-+
-+         /* Only generate callbacks for non-dummy bulk requests */
-+         if (bulk->data)
-+         {
-+            if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED)
-+            {
-+               if (bulk->dir == VCHIQ_BULK_TRANSMIT)
-+               {
-+                  VCHIQ_SERVICE_STATS_INC(service, bulk_tx_count);
-+                  VCHIQ_SERVICE_STATS_ADD(service, bulk_tx_bytes, bulk->actual);
-+               }
-+               else
-+               {
-+                  VCHIQ_SERVICE_STATS_INC(service, bulk_rx_count);
-+                  VCHIQ_SERVICE_STATS_ADD(service, bulk_rx_bytes, bulk->actual);
-+               }
-+            }
-+            else
-+            {
-+               VCHIQ_SERVICE_STATS_INC(service, bulk_aborted_count);
-+            }
-+            if (bulk->mode == VCHIQ_BULK_MODE_BLOCKING)
-+            {
-+               BULK_WAITER_T *waiter = (BULK_WAITER_T *)bulk->userdata;
-+               if (waiter)
-+               {
-+                  waiter->actual = bulk->actual;
-+                  vcos_event_signal(&waiter->event);
-+               }
-+            }
-+            else if (bulk->mode == VCHIQ_BULK_MODE_CALLBACK)
-+            {
-+               VCHIQ_REASON_T reason = (bulk->dir == VCHIQ_BULK_TRANSMIT) ?
-+                  ((bulk->actual == VCHIQ_BULK_ACTUAL_ABORTED) ?
-+                     VCHIQ_BULK_TRANSMIT_ABORTED : VCHIQ_BULK_TRANSMIT_DONE) :
-+                  ((bulk->actual == VCHIQ_BULK_ACTUAL_ABORTED) ?
-+                     VCHIQ_BULK_RECEIVE_ABORTED : VCHIQ_BULK_RECEIVE_DONE);
-+               status = make_service_callback(service, reason,
-+                  NULL, bulk->userdata);
-+               if (status == VCHIQ_RETRY)
-+                  break;
-+            }
-+         }
-+
-+         queue->remove++;
-+         vcos_event_signal(&service->bulk_remove_event);
-+      }
-+   }
-+
-+   if (status != VCHIQ_SUCCESS)
-+      request_poll(service->state, service, (queue == &service->bulk_tx) ?
-+         VCHIQ_POLL_TXNOTIFY : VCHIQ_POLL_RXNOTIFY);
-+
-+   return status;
-+}
-+
-+/* Called by the slot handler thread */
-+static void
-+poll_services(VCHIQ_STATE_T *state)
-+{
-+   int group, i;
-+
-+   for (group = 0; group < BITSET_SIZE(state->unused_service); group++)
-+   {
-+      uint32_t flags;
-+      flags = vcos_atomic_flags_get_and_clear(&state->poll_services[group]);
-+      for (i = 0; flags; i++)
-+      {
-+         if (flags & (1 << i))
-+         {
-+            VCHIQ_SERVICE_T *service = state->services[(group<<5) + i];
-+            uint32_t service_flags =
-+               vcos_atomic_flags_get_and_clear(&service->poll_flags);
-+            if (service_flags & (1 << VCHIQ_POLL_TERMINATE))
-+            {
-+               vcos_log_info("%d: ps - terminate %d<->%d", state->id, service->localport, service->remoteport);
-+               if (vchiq_close_service_internal(service, 0/*!close_recvd*/) != VCHIQ_SUCCESS)
-+                  request_poll(state, service, VCHIQ_POLL_TERMINATE);
-+            }
-+            if (service_flags & (1 << VCHIQ_POLL_TXNOTIFY))
-+               notify_bulks(service, &service->bulk_tx);
-+            if (service_flags & (1 << VCHIQ_POLL_RXNOTIFY))
-+               notify_bulks(service, &service->bulk_rx);
-+            flags &= ~(1 << i);
-+         }
-+      }
-+   }
-+}
-+
-+/* Called by the slot handler or application threads, holding the bulk mutex. */
-+static int
-+resolve_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue)
-+{
-+   VCHIQ_STATE_T *state = service->state;
-+   int resolved = 0;
-+
-+   while ((queue->process != queue->local_insert) &&
-+      (queue->process != queue->remote_insert))
-+   {
-+      VCHIQ_BULK_T *bulk = &queue->bulks[BULK_INDEX(queue->process)];
-+
-+      vcos_log_trace("%d: rb:%d %cx - li=%x ri=%x p=%x",
-+         state->id, service->localport,
-+         (queue == &service->bulk_tx) ? 't' : 'r',
-+         queue->local_insert, queue->remote_insert,
-+         queue->process);
-+
-+      vcos_assert((int)(queue->local_insert - queue->process) > 0);
-+      vcos_assert((int)(queue->remote_insert - queue->process) > 0);
-+      vchiq_transfer_bulk(bulk);
-+
-+      if (vcos_is_log_enabled( &vchiq_core_msg_log_category, VCOS_LOG_INFO))
-+      {
-+         const char *header = (queue == &service->bulk_tx) ?
-+            "Send Bulk to" : "Recv Bulk from";
-+         if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED)
-+            vcos_log_impl( &vchiq_core_msg_log_category,
-+               VCOS_LOG_INFO,
-+               "%s %c%c%c%c d:%d len:%d %x<->%x",
-+               header,
-+               VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc),
-+               service->remoteport,
-+               bulk->size,
-+               (unsigned int)bulk->data,
-+               (unsigned int)bulk->remote_data );
-+         else
-+            vcos_log_impl( &vchiq_core_msg_log_category,
-+               VCOS_LOG_INFO,
-+               "%s %c%c%c%c d:%d ABORTED - tx len:%d, rx len:%d %x<->%x",
-+               header,
-+               VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc),
-+               service->remoteport,
-+               bulk->size,
-+               bulk->remote_size,
-+               (unsigned int)bulk->data,
-+               (unsigned int)bulk->remote_data );
-+      }
-+
-+      vchiq_complete_bulk(bulk);
-+      queue->process++;
-+      resolved++;
-+   }
-+   return resolved;
-+}
-+
-+/* Called with the bulk_mutex held */
-+static void
-+abort_outstanding_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue)
-+{
-+   int is_tx = (queue == &service->bulk_tx);
-+   vcos_log_trace("%d: aob:%d %cx - li=%x ri=%x p=%x",
-+      service->state->id, service->localport, is_tx ? 't' : 'r',
-+      queue->local_insert, queue->remote_insert, queue->process);
-+
-+   vcos_assert((int)(queue->local_insert - queue->process) >= 0);
-+   vcos_assert((int)(queue->remote_insert - queue->process) >= 0);
-+
-+   while ((queue->process != queue->local_insert) ||
-+      (queue->process != queue->remote_insert))
-+   {
-+      VCHIQ_BULK_T *bulk = &queue->bulks[BULK_INDEX(queue->process)];
-+
-+      if (queue->process == queue->remote_insert)
-+      {
-+         /* fabricate a matching dummy bulk */
-+         bulk->remote_data = NULL;
-+         bulk->remote_size = 0;
-+         queue->remote_insert++;
-+      }
-+
-+      if (queue->process != queue->local_insert)
-+      {
-+         vchiq_complete_bulk(bulk);
-+
-+         if (vcos_is_log_enabled( &vchiq_core_msg_log_category, VCOS_LOG_INFO))
-+         {
-+            vcos_log_impl( &vchiq_core_msg_log_category,
-+               VCOS_LOG_INFO,
-+               "%s %c%c%c%c d:%d ABORTED - tx len:%d, rx len:%d",
-+               is_tx ? "Send Bulk to" : "Recv Bulk from",
-+               VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc),
-+               service->remoteport,
-+               bulk->size,
-+               bulk->remote_size );
-+         }
-+      }
-+      else
-+      {
-+         /* fabricate a matching dummy bulk */
-+         bulk->data = NULL;
-+         bulk->size = 0;
-+         bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED;
-+         bulk->dir = is_tx ? VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE;
-+         queue->local_insert++;
-+      }
-+
-+      queue->process++;
-+   }
-+}
-+
-+static void
-+pause_bulks(VCHIQ_STATE_T *state)
-+{
-+   int i;
-+
-+   /* Block bulk transfers from all services */
-+   for (i = 0; i < state->unused_service; i++)
-+   {
-+      VCHIQ_SERVICE_T *service = state->services[i];
-+      if (!service || (service->srvstate != VCHIQ_SRVSTATE_OPEN))
-+         continue;
-+
-+      vcos_log_trace("locking bulk_mutex for service %d", i);
-+      vcos_mutex_lock(&service->bulk_mutex);
-+   }
-+}
-+
-+static void
-+resume_bulks(VCHIQ_STATE_T *state)
-+{
-+   int i;
-+
-+   /* Poll all services in case any bulk transfers have been
-+      deferred */
-+   for (i = 0; i < state->unused_service; i++)
-+   {
-+      VCHIQ_SERVICE_T *service = state->services[i];
-+      if (!service || (service->srvstate != VCHIQ_SRVSTATE_OPEN))
-+         continue;
-+
-+      if (resolve_bulks(service, &service->bulk_tx))
-+         request_poll(state, service, VCHIQ_POLL_TXNOTIFY);
-+      if (resolve_bulks(service, &service->bulk_rx))
-+         request_poll(state, service, VCHIQ_POLL_RXNOTIFY);
-+      vcos_log_trace("unlocking bulk_mutex for service %d", i);
-+      vcos_mutex_unlock(&service->bulk_mutex);
-+   }
-+}
-+
-+/* Called by the slot handler thread */
-+static void
-+parse_rx_slots(VCHIQ_STATE_T *state)
-+{
-+   VCHIQ_SHARED_STATE_T *remote = state->remote;
-+   int tx_pos;
-+   DEBUG_INITIALISE(state->local)
-+
-+   tx_pos = remote->tx_pos;
-+
-+   while (state->rx_pos != tx_pos) {
-+      VCHIQ_SERVICE_T *service = NULL;
-+      VCHIQ_HEADER_T *header;
-+      int msgid, size;
-+      int type;
-+      unsigned int localport, remoteport;
-+
-+      DEBUG_TRACE(PARSE_LINE);
-+      if (!state->rx_data)
-+      {
-+         int rx_index;
-+         vcos_assert((state->rx_pos & VCHIQ_SLOT_MASK) == 0);
-+         rx_index = remote->slot_queue[SLOT_QUEUE_INDEX_FROM_POS(state->rx_pos) & VCHIQ_SLOT_QUEUE_MASK];
-+         state->rx_data = (char *)SLOT_DATA_FROM_INDEX(state, rx_index);
-+         state->rx_info = SLOT_INFO_FROM_INDEX(state, rx_index);
-+
-+         /* Initialise use_count to one, and increment release_count at the end
-+            of the slot to avoid releasing the slot prematurely. */
-+         state->rx_info->use_count = 1;
-+         state->rx_info->release_count = 0;
-+      }
-+
-+      header = (VCHIQ_HEADER_T *)(state->rx_data + (state->rx_pos & VCHIQ_SLOT_MASK));
-+      DEBUG_VALUE(PARSE_HEADER, (int)header);
-+      msgid = header->msgid;
-+      DEBUG_VALUE(PARSE_MSGID, msgid);
-+      size = header->size;
-+      type = VCHIQ_MSG_TYPE(msgid);
-+      localport = VCHIQ_MSG_DSTPORT(msgid);
-+      remoteport = VCHIQ_MSG_SRCPORT(msgid);
-+
-+      if (type != VCHIQ_MSG_DATA)
-+      {
-+         VCHIQ_STATS_INC(state, ctrl_rx_count);
-+      }
-+
-+      switch (type)
-+      {
-+      case VCHIQ_MSG_OPENACK:
-+      case VCHIQ_MSG_CLOSE:
-+      case VCHIQ_MSG_DATA:
-+      case VCHIQ_MSG_BULK_RX:
-+      case VCHIQ_MSG_BULK_TX:
-+      case VCHIQ_MSG_BULK_RX_DONE:
-+      case VCHIQ_MSG_BULK_TX_DONE:
-+         if (localport <= VCHIQ_PORT_MAX)
-+         {
-+            service = state->services[localport];
-+            if (service && (service->srvstate == VCHIQ_SRVSTATE_FREE))
-+               service = NULL;
-+         }
-+         if (!service)
-+         {
-+            vcos_log_error(
-+               "%d: prs %s@%x (%d->%d) - invalid/closed service %d",
-+               state->id, msg_type_str(type), (unsigned int)header,
-+               remoteport, localport, localport);
-+            goto skip_message;
-+         }
-+      default:
-+         break;
-+      }
-+
-+      if ( vcos_is_log_enabled( &vchiq_core_msg_log_category, VCOS_LOG_INFO))
-+      {
-+         int svc_fourcc;
-+
-+         svc_fourcc = service
-+            ? service->base.fourcc
-+            : VCHIQ_MAKE_FOURCC('?','?','?','?');
-+         vcos_log_impl( &vchiq_core_msg_log_category,
-+            VCOS_LOG_INFO,
-+            "Rcvd Msg %s(%u) from %c%c%c%c s:%d d:%d len:%d",
-+            msg_type_str(type), type,
-+            VCHIQ_FOURCC_AS_4CHARS(svc_fourcc),
-+            remoteport, localport, size );
-+         if (size > 0) {
-+            vcos_log_dump_mem( &vchiq_core_msg_log_category,
-+                           "Rcvd", 0, header->data,
-+                           vcos_min( 64, size ));
-+         }
-+      }
-+
-+      if (((unsigned int)header & VCHIQ_SLOT_MASK) + calc_stride(size) > VCHIQ_SLOT_SIZE)
-+      {
-+         vcos_log_error("header %x (msgid %x) - size %x too big for slot",
-+            (unsigned int)header, (unsigned int)msgid, (unsigned int)size);
-+         vcos_assert(0);
-+      }
-+
-+      switch (type) {
-+      case VCHIQ_MSG_OPEN:
-+         vcos_assert(VCHIQ_MSG_DSTPORT(msgid) == 0);
-+         if (vcos_verify(size == sizeof(VCHIQ_OPEN_PAYLOAD_T))) {
-+            const VCHIQ_OPEN_PAYLOAD_T *payload = (VCHIQ_OPEN_PAYLOAD_T *)header->data;
-+            unsigned int fourcc;
-+
-+            fourcc = payload->fourcc;
-+            vcos_log_info("%d: prs OPEN@%x (%d->'%c%c%c%c')",
-+               state->id, (unsigned int)header,
-+               localport,
-+               VCHIQ_FOURCC_AS_4CHARS(fourcc));
-+
-+            service = get_listening_service(state, fourcc);
-+
-+            if (service)
-+            {
-+               /* A matching service exists */
-+               short version = payload->version;
-+               short version_min = payload->version_min;
-+               if ((service->version < version_min) ||
-+                  (version < service->version_min))
-+               {
-+                  /* Version mismatch */
-+                  vcos_log_error("%d: service %d (%c%c%c%c) version mismatch -"
-+                     " local (%d, min %d) vs. remote (%d, min %d)",
-+                     state->id, service->localport,
-+                     VCHIQ_FOURCC_AS_4CHARS(fourcc),
-+                     service->version, service->version_min,
-+                     version, version_min);
-+                  goto fail_open;
-+               }
-+               if (service->srvstate == VCHIQ_SRVSTATE_LISTENING)
-+               {
-+                  /* Acknowledge the OPEN */
-+                  if (queue_message(state, NULL,
-+                     VCHIQ_MAKE_MSG(VCHIQ_MSG_OPENACK, service->localport, remoteport),
-+                     NULL, 0, 0, 0) == VCHIQ_RETRY)
-+                     return;  /* Bail out if not ready */
-+
-+                  /* The service is now open */
-+                  vchiq_set_service_state(service, VCHIQ_SRVSTATE_OPEN);
-+               }
-+
-+               service->remoteport = remoteport;
-+               service->client_id = ((int *)header->data)[1];
-+               if (make_service_callback(service, VCHIQ_SERVICE_OPENED,
-+                  NULL, NULL) == VCHIQ_RETRY)
-+               {
-+                  /* Bail out if not ready */
-+                  service->remoteport = VCHIQ_PORT_FREE;
-+                  return;
-+               }
-+
-+               /* Break out, and skip the failure handling */
-+               break;
-+            }
-+         }
-+      fail_open:
-+         /* No available service, or an invalid request - send a CLOSE */
-+         if (queue_message(state, NULL,
-+            VCHIQ_MAKE_MSG(VCHIQ_MSG_CLOSE, 0, VCHIQ_MSG_SRCPORT(msgid)),
-+            NULL, 0, 0, 0) == VCHIQ_RETRY)
-+            return;  /* Bail out if not ready */
-+         break;
-+      case VCHIQ_MSG_OPENACK:
-+         {
-+            vcos_log_info("%d: prs OPENACK@%x (%d->%d)",
-+               state->id, (unsigned int)header,
-+               remoteport, localport);
-+            if (service->srvstate == VCHIQ_SRVSTATE_OPENING) {
-+               service->remoteport = remoteport;
-+               vchiq_set_service_state(service,
-+                        VCHIQ_SRVSTATE_OPEN);
-+               vcos_event_signal(&service->remove_event);
-+            }
-+         }
-+         break;
-+      case VCHIQ_MSG_CLOSE:
-+         {
-+            vcos_assert(size == 0); /* There should be no data */
-+
-+            vcos_log_info("%d: prs CLOSE@%x (%d->%d)",
-+               state->id, (unsigned int)header,
-+               remoteport, localport);
-+
-+            if ((service->remoteport != remoteport) &&
-+               VCHIQ_PORT_IS_VALID(service->remoteport)) {
-+               /* This could be from a client which hadn't yet received
-+                  the OPENACK - look for the connected service */
-+               service = get_connected_service(state, remoteport);
-+               if (!service)
-+                  break;
-+            }
-+
-+            if (vchiq_close_service_internal(service,
-+               1/*close_recvd*/) == VCHIQ_RETRY)
-+               return;  /* Bail out if not ready */
-+
-+            if (vcos_is_log_enabled( &vchiq_core_msg_log_category, VCOS_LOG_INFO))
-+            {
-+               vcos_log_impl( &vchiq_core_msg_log_category,
-+                           VCOS_LOG_INFO,
-+                           "Close Service %c%c%c%c s:%u d:%d",
-+                           VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc),
-+                           service->localport,
-+                           service->remoteport );
-+            }
-+         }
-+         break;
-+      case VCHIQ_MSG_DATA:
-+         {
-+            vcos_log_trace("%d: prs DATA@%x,%x (%d->%d)",
-+               state->id, (unsigned int)header, size,
-+               remoteport, localport);
-+
-+            if ((service->remoteport == remoteport)
-+               && (service->srvstate ==
-+               VCHIQ_SRVSTATE_OPEN)) {
-+               header->msgid = msgid | VCHIQ_MSGID_CLAIMED;
-+               claim_slot(state->rx_info);
-+               DEBUG_TRACE(PARSE_LINE);
-+               if (make_service_callback(service,
-+                  VCHIQ_MESSAGE_AVAILABLE, header,
-+                  NULL) == VCHIQ_RETRY)
-+               {
-+                  DEBUG_TRACE(PARSE_LINE);
-+                  return;  /* Bail out if not ready */
-+               }
-+               VCHIQ_SERVICE_STATS_INC(service, ctrl_rx_count);
-+               VCHIQ_SERVICE_STATS_ADD(service, ctrl_rx_bytes, size);
-+            }
-+            else
-+            {
-+               VCHIQ_STATS_INC(state, error_count);
-+            }
-+         }
-+         break;
-+      case VCHIQ_MSG_CONNECT:
-+         vcos_log_info("%d: prs CONNECT@%x",
-+            state->id, (unsigned int)header);
-+         vcos_event_signal(&state->connect);
-+         break;
-+      case VCHIQ_MSG_BULK_RX:
-+      case VCHIQ_MSG_BULK_TX:
-+         {
-+            VCHIQ_BULK_QUEUE_T *queue;
-+            vcos_assert(state->is_master);
-+            queue = (type == VCHIQ_MSG_BULK_RX) ?
-+               &service->bulk_tx : &service->bulk_rx;
-+            if ((service->remoteport == remoteport)
-+               && (service->srvstate ==
-+               VCHIQ_SRVSTATE_OPEN))
-+            {
-+               VCHIQ_BULK_T *bulk;
-+               int resolved;
-+
-+               vcos_assert(queue->remote_insert < queue->remove +
-+                  VCHIQ_NUM_SERVICE_BULKS);
-+               bulk = &queue->bulks[BULK_INDEX(queue->remote_insert)];
-+               bulk->remote_data = (void *)((int *)header->data)[0];
-+               bulk->remote_size = ((int *)header->data)[1];
-+
-+               vcos_log_info("%d: prs %s@%x (%d->%d) %x@%x",
-+                  state->id, msg_type_str(type),
-+                  (unsigned int)header,
-+                  remoteport, localport,
-+                  bulk->remote_size,
-+                  (unsigned int)bulk->remote_data);
-+
-+               queue->remote_insert++;
-+
-+               if (state->conn_state != VCHIQ_CONNSTATE_CONNECTED)
-+                  break;
-+
-+               DEBUG_TRACE(PARSE_LINE);
-+               if (vcos_mutex_lock(&service->bulk_mutex) != VCOS_SUCCESS)
-+               {
-+                  DEBUG_TRACE(PARSE_LINE);
-+                  return;
-+               }
-+               DEBUG_TRACE(PARSE_LINE);
-+               resolved = resolve_bulks(service, queue);
-+               vcos_mutex_unlock(&service->bulk_mutex);
-+               if (resolved)
-+                  notify_bulks(service, queue);
-+            }
-+         }
-+         break;
-+      case VCHIQ_MSG_BULK_RX_DONE:
-+      case VCHIQ_MSG_BULK_TX_DONE:
-+         {
-+            vcos_assert(!state->is_master);
-+            if ((service->remoteport == remoteport)
-+               && (service->srvstate !=
-+               VCHIQ_SRVSTATE_FREE)) {
-+               VCHIQ_BULK_QUEUE_T *queue;
-+               VCHIQ_BULK_T *bulk;
-+
-+               queue = (type == VCHIQ_MSG_BULK_RX_DONE) ?
-+                  &service->bulk_rx : &service->bulk_tx;
-+
-+               bulk = &queue->bulks[BULK_INDEX(queue->process)];
-+               bulk->actual = *(int *)header->data;
-+
-+               vcos_log_info("%d: prs %s@%x (%d->%d) %x@%x",
-+                  state->id, msg_type_str(type),
-+                  (unsigned int)header,
-+                  remoteport, localport,
-+                  bulk->actual, (unsigned int)bulk->data);
-+
-+               vcos_log_trace("%d: prs:%d %cx li=%x ri=%x p=%x",
-+                  state->id, localport,
-+                  (type == VCHIQ_MSG_BULK_RX_DONE) ? 'r' : 't',
-+                  queue->local_insert,
-+                  queue->remote_insert, queue->process);
-+
-+               DEBUG_TRACE(PARSE_LINE);
-+               if (vcos_mutex_lock(&service->bulk_mutex) != VCOS_SUCCESS)
-+               {
-+                  DEBUG_TRACE(PARSE_LINE);
-+                  return;
-+               }
-+               DEBUG_TRACE(PARSE_LINE);
-+               vcos_assert(queue->process != queue->local_insert);
-+               vchiq_complete_bulk(bulk);
-+               queue->process++;
-+               vcos_mutex_unlock(&service->bulk_mutex);
-+               DEBUG_TRACE(PARSE_LINE);
-+               notify_bulks(service, queue);
-+               DEBUG_TRACE(PARSE_LINE);
-+            }
-+         }
-+         break;
-+      case VCHIQ_MSG_PADDING:
-+         vcos_log_trace("%d: prs PADDING@%x,%x",
-+            state->id, (unsigned int)header, size);
-+         break;
-+      case VCHIQ_MSG_PAUSE:
-+         /* If initiated, signal the application thread */
-+         vcos_log_trace("%d: prs PAUSE@%x,%x",
-+            state->id, (unsigned int)header, size);
-+         if (state->conn_state != VCHIQ_CONNSTATE_PAUSE_SENT)
-+         {
-+            /* Send a PAUSE in response */
-+            if (queue_message(state, NULL,
-+               VCHIQ_MAKE_MSG(VCHIQ_MSG_PAUSE, 0, 0),
-+               NULL, 0, 0, 0) == VCHIQ_RETRY)
-+               return;  /* Bail out if not ready */
-+            if (state->is_master)
-+               pause_bulks(state);
-+         }
-+         /* At this point slot_mutex is held */
-+         vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSED);
-+         vchiq_platform_paused(state);
-+         break;
-+      case VCHIQ_MSG_RESUME:
-+         vcos_log_trace("%d: prs RESUME@%x,%x",
-+            state->id, (unsigned int)header, size);
-+         /* Release the slot mutex */
-+         vcos_mutex_unlock(&state->slot_mutex);
-+         if (state->is_master)
-+            resume_bulks(state);
-+         vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED);
-+         vchiq_platform_resumed(state);
-+         break;
-+      default:
-+         vcos_log_error("%d: prs invalid msgid %x@%x,%x",
-+            state->id, msgid, (unsigned int)header, size);
-+         vcos_assert(0);
-+         break;
-+      }
-+
-+   skip_message:
-+      state->rx_pos += calc_stride(size);
-+
-+      DEBUG_TRACE(PARSE_LINE);
-+      /* Perform some housekeeping when the end of the slot is reached. */
-+      if ((state->rx_pos & VCHIQ_SLOT_MASK) == 0)
-+      {
-+         /* Remove the extra reference count. */
-+         release_slot(state, state->rx_info);
-+         state->rx_data = NULL;
-+      }
-+   }
-+}
-+
-+/* Called by the slot handler thread */
-+static void *
-+slot_handler_func(void *v)
-+{
-+   VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v;
-+   VCHIQ_SHARED_STATE_T *local = state->local;
-+   DEBUG_INITIALISE(local)
-+
-+   while (1) {
-+      DEBUG_COUNT(SLOT_HANDLER_COUNT);
-+      DEBUG_TRACE(SLOT_HANDLER_LINE);
-+      remote_event_wait(&local->trigger);
-+
-+      vcos_rmb();
-+
-+      DEBUG_TRACE(SLOT_HANDLER_LINE);
-+      if (state->poll_needed)
-+      {
-+         state->poll_needed = 0;
-+
-+         /* Handle service polling and other rare conditions here out
-+            of the mainline code */
-+         switch (state->conn_state)
-+         {
-+         case VCHIQ_CONNSTATE_CONNECTED:
-+            /* Poll the services as requested */
-+            poll_services(state);
-+            break;
-+
-+         case VCHIQ_CONNSTATE_PAUSING:
-+            if (queue_message(state, NULL,
-+               VCHIQ_MAKE_MSG(VCHIQ_MSG_PAUSE, 0, 0), NULL, 0, 0, 0)
-+               != VCHIQ_RETRY)
-+            {
-+               if (state->is_master)
-+                  pause_bulks(state);
-+               vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSE_SENT);
-+            }
-+            else
-+            {
-+               state->poll_needed = 1; /* Retry later */
-+            }
-+            break;
-+
-+         case VCHIQ_CONNSTATE_RESUMING:
-+            if (queue_message(state, NULL,
-+               VCHIQ_MAKE_MSG(VCHIQ_MSG_RESUME, 0, 0), NULL, 0, 0, 0)
-+               != VCHIQ_RETRY)
-+            {
-+               if (state->is_master)
-+                  resume_bulks(state);
-+               vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED);
-+               vchiq_platform_resumed(state);
-+            }
-+            else
-+            {
-+               /* This should really be impossible, since the PAUSE should
-+                  have flushed through outstanding messages. */
-+               vcos_log_error("Failed to send RESUME message");
-+               vcos_demand(0);
-+            }
-+            break;
-+         default:
-+            break;
-+         }
-+      }
-+
-+      DEBUG_TRACE(SLOT_HANDLER_LINE);
-+      parse_rx_slots(state);
-+   }
-+   return NULL;
-+}
-+
-+extern VCHIQ_STATUS_T
-+vchiq_platform_suspend(VCHIQ_STATE_T *state);
-+
-+/* Called by the recycle thread */
-+static void *
-+recycle_func(void *v)
-+{
-+   VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v;
-+   VCHIQ_SHARED_STATE_T *local = state->local;
-+
-+   while (1) {
-+      remote_event_wait(&local->recycle);
-+
-+      vcos_mutex_lock(&state->slot_mutex);
-+
-+      process_free_queue(state);
-+
-+      vcos_mutex_unlock(&state->slot_mutex);
-+   }
-+   return NULL;
-+}
-+
-+/* Called by the lp thread */
-+static void *
-+lp_func(void *v)
-+{
-+   VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v;
-+
-+   while (1) {
-+      vcos_event_wait(&state->lp_evt);
-+      vcos_mutex_lock(&state->use_count_mutex);
-+      if (state->videocore_use_count == 0)
-+      {
-+         vchiq_platform_suspend(state);
-+      }
-+      vcos_mutex_unlock(&state->use_count_mutex);
-+   }
-+   return NULL;
-+}
-+
-+static void
-+init_bulk_queue(VCHIQ_BULK_QUEUE_T *queue)
-+{
-+   queue->local_insert = 0;
-+   queue->remote_insert = 0;
-+   queue->process = 0;
-+   queue->remote_notify = 0;
-+   queue->remove = 0;
-+}
-+
-+VCHIQ_SLOT_ZERO_T *
-+vchiq_init_slots(void *mem_base, int mem_size)
-+{
-+   int mem_align = (VCHIQ_SLOT_SIZE - (int)mem_base) & VCHIQ_SLOT_MASK;
-+   VCHIQ_SLOT_ZERO_T *slot_zero = (VCHIQ_SLOT_ZERO_T *)((char *)mem_base + mem_align);
-+   int num_slots = (mem_size - mem_align)/VCHIQ_SLOT_SIZE;
-+   int first_data_slot = VCHIQ_SLOT_ZERO_SLOTS;
-+
-+   /* Ensure there is enough memory to run an absolutely minimum system */
-+   num_slots -= first_data_slot;
-+
-+   if (num_slots < 4)
-+   {
-+      vcos_log_error("vchiq_init_slots - insufficient memory %x bytes", mem_size);
-+      return NULL;
-+   }
-+
-+   memset(slot_zero, 0, sizeof(VCHIQ_SLOT_ZERO_T));
-+
-+   slot_zero->magic = VCHIQ_MAGIC;
-+   slot_zero->version = VCHIQ_VERSION;
-+   slot_zero->version_min = VCHIQ_VERSION_MIN;
-+   slot_zero->slot_zero_size = sizeof(VCHIQ_SLOT_ZERO_T);
-+   slot_zero->slot_size = VCHIQ_SLOT_SIZE;
-+   slot_zero->max_slots = VCHIQ_MAX_SLOTS;
-+   slot_zero->max_slots_per_side = VCHIQ_MAX_SLOTS_PER_SIDE;
-+
-+   slot_zero->master.slot_first = first_data_slot;
-+   slot_zero->slave.slot_first = first_data_slot + (num_slots/2);
-+   slot_zero->master.slot_last = slot_zero->slave.slot_first - 1;
-+   slot_zero->slave.slot_last = first_data_slot + num_slots - 1;
-+
-+   return slot_zero;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, int is_master)
-+{
-+   VCHIQ_SHARED_STATE_T *local;
-+   VCHIQ_SHARED_STATE_T *remote;
-+   VCOS_THREAD_ATTR_T attrs;
-+   char threadname[10];
-+   static int id = 0;
-+   int i;
-+
-+   vcos_log_set_level(&vchiq_core_log_category, vchiq_default_core_log_level);
-+   vcos_log_set_level(&vchiq_core_msg_log_category, vchiq_default_core_msg_log_level);
-+   vcos_log_register("vchiq_core", &vchiq_core_log_category);
-+   vcos_log_register("vchiq_core_msg", &vchiq_core_msg_log_category);
-+
-+   vcos_log_warn( "%s: slot_zero = 0x%08lx, is_master = %d\n", __func__, (unsigned long)slot_zero, is_master );
-+
-+   /* Check the input configuration */
-+
-+   if (slot_zero->magic != VCHIQ_MAGIC)
-+   {
-+      vcos_log_error("slot_zero=%x: magic=%x (expected %x)",
-+         (unsigned int)slot_zero, slot_zero->magic, VCHIQ_MAGIC);
-+      return VCHIQ_ERROR;
-+   }
-+
-+   if (slot_zero->version < VCHIQ_VERSION_MIN)
-+   {
-+      vcos_log_error("slot_zero=%x: peer_version=%x (minimum %x)",
-+         (unsigned int)slot_zero, slot_zero->version, VCHIQ_VERSION_MIN);
-+      return VCHIQ_ERROR;
-+   }
-+
-+   if (VCHIQ_VERSION < slot_zero->version_min)
-+   {
-+      vcos_log_error("slot_zero=%x: version=%x (peer minimum %x)",
-+         (unsigned int)slot_zero, VCHIQ_VERSION, slot_zero->version_min);
-+      return VCHIQ_ERROR;
-+   }
-+
-+   if (slot_zero->slot_zero_size != sizeof(VCHIQ_SLOT_ZERO_T))
-+   {
-+      vcos_log_error("slot_zero=%x: slot_zero_size=%x (expected %x)",
-+         (unsigned int)slot_zero, slot_zero->slot_zero_size, sizeof(VCHIQ_SLOT_ZERO_T));
-+      return VCHIQ_ERROR;
-+   }
-+
-+   if (slot_zero->slot_size != VCHIQ_SLOT_SIZE)
-+   {
-+      vcos_log_error("slot_zero=%x: slot_size=%d (expected %d",
-+         (unsigned int)slot_zero, slot_zero->slot_size, VCHIQ_SLOT_SIZE);
-+      return VCHIQ_ERROR;
-+   }
-+
-+   if (slot_zero->max_slots != VCHIQ_MAX_SLOTS)
-+   {
-+      vcos_log_error("slot_zero=%x: max_slots=%d (expected %d)",
-+         (unsigned int)slot_zero, slot_zero->max_slots, VCHIQ_MAX_SLOTS);
-+      return VCHIQ_ERROR;
-+   }
-+
-+   if (slot_zero->max_slots_per_side != VCHIQ_MAX_SLOTS_PER_SIDE)
-+   {
-+      vcos_log_error("slot_zero=%x: max_slots_per_side=%d (expected %d)",
-+         (unsigned int)slot_zero, slot_zero->max_slots_per_side,
-+         VCHIQ_MAX_SLOTS_PER_SIDE);
-+      return VCHIQ_ERROR;
-+   }
-+
-+   if (is_master)
-+   {
-+      local = &slot_zero->master;
-+      remote = &slot_zero->slave;
-+   }
-+   else
-+   {
-+      local = &slot_zero->slave;
-+      remote = &slot_zero->master;
-+   }
-+
-+   if (local->initialised)
-+   {
-+      if (remote->initialised)
-+         vcos_log_error("vchiq: FATAL: local state has already been initialised");
-+      else
-+         vcos_log_error("vchiq: FATAL: master/slave mismatch - two %ss", is_master ? "master" : "slave");
-+      return VCHIQ_ERROR;
-+   }
-+
-+   memset(state, 0, sizeof(VCHIQ_STATE_T));
-+   state->id = id++;
-+   state->is_master = is_master;
-+
-+   /*
-+      initialize shared state pointers
-+    */
-+
-+   state->local = local;
-+   state->remote = remote;
-+   state->slot_data = (VCHIQ_SLOT_T *)slot_zero;
-+
-+   /*
-+      initialize events and mutexes
-+    */
-+
-+   vcos_event_create(&state->connect, "v.connect");
-+   vcos_mutex_create(&state->mutex, "v.mutex");
-+   vcos_event_create(&state->trigger_event, "v.trigger_event");
-+   vcos_event_create(&state->recycle_event, "v.recycle_event");
-+
-+   vcos_mutex_create(&state->slot_mutex, "v.slot_mutex");
-+   vcos_mutex_create(&state->recycle_mutex, "v.recycle_mutex");
-+   vcos_mutex_create(&state->use_count_mutex, "v.use_count_mutex");
-+   vcos_mutex_create(&state->suspend_resume_mutex, "v.susp_res_mutex");
-+
-+   vcos_event_create(&state->slot_available_event, "v.slot_available_event");
-+   vcos_event_create(&state->slot_remove_event, "v.slot_remove_event");
-+
-+   state->slot_queue_available = 0;
-+
-+   for (i = 0; i < VCHIQ_MAX_SERVICES; i++)
-+   {
-+      VCHIQ_SERVICE_QUOTA_T *service_quota = &state->service_quotas[i];
-+      vcos_event_create(&service_quota->quota_event, "v.quota_event");
-+   }
-+
-+   for (i = local->slot_first; i <= local->slot_last; i++)
-+   {
-+      local->slot_queue[state->slot_queue_available++] = i;
-+   }
-+
-+   state->default_slot_quota = state->slot_queue_available/2;
-+
-+   local->trigger.event = &state->trigger_event;
-+   remote_event_create(&local->trigger);
-+   local->tx_pos = 0;
-+
-+   local->recycle.event = &state->recycle_event;
-+   remote_event_create(&local->recycle);
-+   local->slot_queue_recycle = state->slot_queue_available;
-+
-+   vcos_event_create(&state->lp_evt, "LP_EVT");
-+
-+   local->debug[DEBUG_ENTRIES] = DEBUG_MAX;
-+
-+   /*
-+      bring up slot handler thread
-+    */
-+
-+   vcos_thread_attr_init(&attrs);
-+   vcos_thread_attr_setstacksize(&attrs, VCHIQ_SLOT_HANDLER_STACK);
-+   vcos_thread_attr_setpriority(&attrs, VCOS_THREAD_PRI_REALTIME);
-+   vcos_snprintf(threadname, sizeof(threadname), "VCHIQ-%d", state->id);
-+   if (vcos_thread_create(&state->slot_handler_thread, threadname,
-+            &attrs, slot_handler_func, state) != VCOS_SUCCESS)
-+      return VCHIQ_ERROR;
-+
-+   vcos_thread_attr_init(&attrs);
-+   vcos_thread_attr_setstacksize(&attrs, VCHIQ_SLOT_HANDLER_STACK);
-+   vcos_thread_attr_setpriority(&attrs, VCOS_THREAD_PRI_REALTIME);
-+   vcos_snprintf(threadname, sizeof(threadname), "VCHIQr-%d", state->id);
-+   if (vcos_thread_create(&state->recycle_thread, threadname,
-+            &attrs, recycle_func, state) != VCOS_SUCCESS)
-+      return VCHIQ_ERROR;
-+
-+   vcos_thread_attr_init(&attrs);
-+   vcos_thread_attr_setstacksize(&attrs, VCHIQ_SLOT_HANDLER_STACK);
-+   vcos_thread_attr_setpriority(&attrs, VCOS_THREAD_PRI_LOWEST);
-+   vcos_snprintf(threadname, sizeof(threadname), "VCHIQl-%d", state->id);
-+   if (vcos_thread_create(&state->lp_thread, threadname,
-+            &attrs, lp_func, state) != VCOS_SUCCESS)
-+      return VCHIQ_ERROR;
-+
-+   /* Indicate readiness to the other side */
-+   local->initialised = 1;
-+
-+   return VCHIQ_SUCCESS;
-+}
-+
-+/* Called from application thread when a client or server service is created. */
-+VCHIQ_SERVICE_T *
-+vchiq_add_service_internal(VCHIQ_STATE_T *state,
-+   const VCHIQ_SERVICE_PARAMS_T *params, int srvstate,
-+   VCHIQ_INSTANCE_T instance)
-+{
-+   VCHIQ_SERVICE_T **pservice = NULL;
-+   VCHIQ_SERVICE_T *service = NULL;
-+   int i;
-+
-+   /* Prepare to use a previously unused service */
-+   if (state->unused_service < VCHIQ_MAX_SERVICES)
-+   {
-+      pservice = &state->services[state->unused_service];
-+   }
-+
-+   if (srvstate == VCHIQ_SRVSTATE_OPENING) {
-+      for (i = 0; i < state->unused_service; i++) {
-+         VCHIQ_SERVICE_T *srv = state->services[i];
-+         if (!srv)
-+         {
-+            pservice = &state->services[i];
-+            break;
-+         }
-+         if (srv->srvstate == VCHIQ_SRVSTATE_FREE) {
-+            service = srv;
-+            break;
-+         }
-+      }
-+   } else {
-+      for (i = (state->unused_service - 1); i >= 0; i--) {
-+         VCHIQ_SERVICE_T *srv = state->services[i];
-+         if (!srv)
-+            pservice = &state->services[i];
-+         else if (srv->srvstate == VCHIQ_SRVSTATE_FREE) {
-+            service = srv;
-+         } else if ((srv->public_fourcc == params->fourcc) &&
-+            ((srv->instance != instance)
-+            || (srv->base.callback != params->callback))) {
-+            /* There is another server using this fourcc which doesn't match */
-+            pservice = NULL;
-+            service = NULL;
-+         }
-+      }
-+   }
-+
-+   if (pservice && !service)
-+   {
-+      service = vcos_malloc(sizeof(VCHIQ_SERVICE_T), "VCHIQ service");
-+      if (service)
-+      {
-+         service->srvstate = VCHIQ_SRVSTATE_FREE;
-+         service->localport = (pservice - state->services);
-+         vcos_event_create(&service->remove_event, "v.remove_event");
-+         vcos_event_create(&service->bulk_remove_event, "v.bulk_remove_event");
-+         vcos_mutex_create(&service->bulk_mutex, "v.bulk_mutex");
-+         *pservice = service;
-+      }
-+      else
-+      {
-+         vcos_log_error("vchiq: Out of memory");
-+      }
-+   }
-+
-+   if (service) {
-+      VCHIQ_SERVICE_QUOTA_T *service_quota =
-+         &state->service_quotas[service->localport];
-+      if (vcos_is_log_enabled( &vchiq_core_msg_log_category, VCOS_LOG_INFO)) {
-+         vcos_log_impl( &vchiq_core_msg_log_category,
-+                     VCOS_LOG_INFO,
-+                     "%s Service %c%c%c%c SrcPort:%d",
-+                     ( srvstate == VCHIQ_SRVSTATE_OPENING )
-+                     ? "Open" : "Add",
-+                     VCHIQ_FOURCC_AS_4CHARS(params->fourcc),
-+                     service->localport );
-+      }
-+      service->state = state;
-+      service->base.fourcc   = params->fourcc;
-+      service->base.callback = params->callback;
-+      service->base.userdata = params->userdata;
-+      service->version       = params->version;
-+      service->version_min   = params->version_min;
-+      vchiq_set_service_state(service, srvstate);
-+      service->public_fourcc =
-+         (srvstate ==
-+         VCHIQ_SRVSTATE_OPENING) ? VCHIQ_FOURCC_INVALID : params->fourcc;
-+      service->instance = instance;
-+      service->remoteport = VCHIQ_PORT_FREE;
-+      service->client_id = 0;
-+      service->auto_close = 1;
-+      service->service_use_count = 0;
-+      init_bulk_queue(&service->bulk_tx);
-+      init_bulk_queue(&service->bulk_rx);
-+      service_quota->slot_quota = state->default_slot_quota;
-+      if (service_quota->slot_use_count == 0)
-+         service_quota->previous_tx_index =
-+            SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos) - 1;
-+      memset(&service->stats, 0, sizeof(service->stats));
-+      vcos_atomic_flags_create(&service->poll_flags);
-+
-+      /* Ensure the events are unsignalled */
-+      while (vcos_event_try(&service->remove_event) == VCOS_SUCCESS)
-+         continue;
-+      while (vcos_event_try(&service_quota->quota_event) == VCOS_SUCCESS)
-+         continue;
-+
-+      if (pservice == &state->services[state->unused_service])
-+         state->unused_service++;
-+   }
-+
-+   return service;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id)
-+{
-+   VCHIQ_OPEN_PAYLOAD_T payload = {
-+      service->base.fourcc,
-+      client_id,
-+      service->version,
-+      service->version_min
-+   };
-+   VCHIQ_ELEMENT_T body = { &payload, sizeof(payload) };
-+   VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
-+
-+   service->client_id = client_id;
-+   vchiq_use_service(&service->base);
-+   status = queue_message(service->state, NULL,
-+                     VCHIQ_MAKE_MSG(VCHIQ_MSG_OPEN, service->localport, 0),
-+                     &body, 1, sizeof(payload), 1);
-+   if (status == VCHIQ_SUCCESS) {
-+      if (vcos_event_wait(&service->remove_event) != VCOS_SUCCESS) {
-+         status = VCHIQ_RETRY;
-+         vchiq_release_service(&service->base);
-+      } else if (service->srvstate != VCHIQ_SRVSTATE_OPEN) {
-+         vcos_log_info("%d: osi - srvstate = %d", service->state->id, service->srvstate);
-+         vcos_assert(service->srvstate == VCHIQ_SRVSTATE_CLOSEWAIT);
-+         status = VCHIQ_ERROR;
-+         VCHIQ_SERVICE_STATS_INC(service, error_count);
-+         vchiq_release_service(&service->base);
-+      }
-+   }
-+   return status;
-+}
-+
-+/* Called by the slot handler */
-+VCHIQ_STATUS_T
-+vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd)
-+{
-+   VCHIQ_STATE_T *state = service->state;
-+   VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
-+
-+   vcos_log_trace("%d: csi:%d (%s)",
-+      service->state->id, service->localport,
-+      srvstate_names[service->srvstate]);
-+
-+   switch (service->srvstate)
-+   {
-+   case VCHIQ_SRVSTATE_OPENING:
-+      if (close_recvd)
-+      {
-+         /* The open was rejected - tell the user */
-+         vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSEWAIT);
-+         vcos_event_signal(&service->remove_event);
-+      }
-+      else
-+      {
-+         /* Shutdown mid-open - let the other side know */
-+         status = queue_message(state, NULL,
-+            VCHIQ_MAKE_MSG
-+            (VCHIQ_MSG_CLOSE,
-+            service->localport,
-+            VCHIQ_MSG_DSTPORT(service->remoteport)),
-+            NULL, 0, 0, 0);
-+
-+         if (status == VCHIQ_SUCCESS)
-+            vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSESENT);
-+      }
-+      break;
-+
-+   case VCHIQ_SRVSTATE_OPEN:
-+      if (state->is_master)
-+      {
-+         /* Abort any outstanding bulk transfers */
-+         vcos_mutex_lock(&service->bulk_mutex);
-+         abort_outstanding_bulks(service, &service->bulk_tx);
-+         abort_outstanding_bulks(service, &service->bulk_rx);
-+         status = notify_bulks(service, &service->bulk_tx);
-+         if (status == VCHIQ_SUCCESS)
-+            status = notify_bulks(service, &service->bulk_rx);
-+         vcos_mutex_unlock(&service->bulk_mutex);
-+      }
-+
-+      if (status == VCHIQ_SUCCESS)
-+         status = queue_message(state, NULL,
-+            VCHIQ_MAKE_MSG
-+            (VCHIQ_MSG_CLOSE,
-+            service->localport,
-+            VCHIQ_MSG_DSTPORT(service->remoteport)),
-+            NULL, 0, 0, 0);
-+
-+      if (status == VCHIQ_SUCCESS)
-+      {
-+         if (close_recvd)
-+            vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSING);
-+         else
-+            vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSESENT);
-+      }
-+      break;
-+
-+   case VCHIQ_SRVSTATE_CLOSESENT:
-+      vcos_assert(close_recvd);
-+
-+      if (!state->is_master)
-+      {
-+         /* Abort any outstanding bulk transfers */
-+         vcos_mutex_lock(&service->bulk_mutex);
-+         abort_outstanding_bulks(service, &service->bulk_tx);
-+         abort_outstanding_bulks(service, &service->bulk_rx);
-+         status = notify_bulks(service, &service->bulk_tx);
-+         if (status == VCHIQ_SUCCESS)
-+            status = notify_bulks(service, &service->bulk_rx);
-+         vcos_mutex_unlock(&service->bulk_mutex);
-+      }
-+
-+      if (status == VCHIQ_SUCCESS)
-+         vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSING);
-+      break;
-+
-+   case VCHIQ_SRVSTATE_CLOSING:
-+      /* We may come here after a retry */
-+      vcos_assert(!close_recvd);
-+      break;
-+
-+   default:
-+      vcos_log_error("vchiq_close_service_internal(%d) called in state %s",
-+         close_recvd, srvstate_names[service->srvstate]);
-+      vcos_assert(0);
-+      break;
-+   }
-+
-+   if (service->srvstate == VCHIQ_SRVSTATE_CLOSING)
-+   {
-+      /* Complete the close process */
-+      vchiq_release_service(&service->base);
-+
-+      service->client_id = 0;
-+
-+      /* Now tell the client that the services is closed */
-+      if (service->instance)
-+      {
-+         int oldstate = service->srvstate;
-+
-+         /* Change the service state now for the benefit of the callback */
-+         vchiq_set_service_state(service,
-+            ((service->public_fourcc == VCHIQ_FOURCC_INVALID) ||
-+            !service->auto_close) ?
-+            VCHIQ_SRVSTATE_CLOSEWAIT :
-+            VCHIQ_SRVSTATE_LISTENING);
-+
-+         status = make_service_callback(service, VCHIQ_SERVICE_CLOSED, NULL, NULL);
-+
-+         if (status == VCHIQ_RETRY)
-+         {
-+            /* Restore the old state, to be retried later */
-+            vchiq_set_service_state(service, oldstate);
-+         }
-+         else
-+         {
-+            if (status == VCHIQ_ERROR) {
-+               /* Signal an error (fatal, since the other end will probably have closed) */
-+               vchiq_set_service_state(service, VCHIQ_SRVSTATE_OPEN);
-+            }
-+         }
-+      }
-+
-+      if (status != VCHIQ_RETRY)
-+      {
-+         if (service->srvstate == VCHIQ_SRVSTATE_CLOSING)
-+            vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSEWAIT);
-+         vcos_event_signal(&service->remove_event);
-+      }
-+   }
-+
-+   return status;
-+}
-+
-+/* Called from the application process upon process death */
-+void
-+vchiq_terminate_service_internal(VCHIQ_SERVICE_T *service)
-+{
-+   VCHIQ_STATE_T *state = service->state;
-+
-+   vcos_log_info("%d: tsi - (%d<->%d)", state->id, service->localport, service->remoteport);
-+
-+   /* Disconnect from the instance, to prevent any callbacks */
-+   service->instance = NULL;
-+
-+   /* Mark the service for termination by the slot handler */
-+   request_poll(state, service, VCHIQ_POLL_TERMINATE);
-+}
-+
-+/* Called from the application process upon process death, and from
-+   vchiq_remove_service */
-+void
-+vchiq_free_service_internal(VCHIQ_SERVICE_T *service)
-+{
-+   VCHIQ_STATE_T *state = service->state;
-+   int slot_last = state->remote->slot_last;
-+   int i;
-+
-+   vcos_log_info("%d: fsi - (%d)", state->id, service->localport);
-+
-+   vcos_mutex_lock(&state->mutex);
-+
-+   /* Release any claimed messages */
-+   for (i = state->remote->slot_first; i <= slot_last; i++)
-+   {
-+      VCHIQ_SLOT_INFO_T *slot_info = SLOT_INFO_FROM_INDEX(state, i);
-+      if (slot_info->release_count != slot_info->use_count)
-+      {
-+         char *data = (char *)SLOT_DATA_FROM_INDEX(state, i);
-+         int pos, end;
-+
-+         end = VCHIQ_SLOT_SIZE;
-+         if (data == state->rx_data)
-+         {
-+            /* This buffer is still being read from - stop at the current read position */
-+            end = state->rx_pos & VCHIQ_SLOT_MASK;
-+         }
-+
-+         pos = 0;
-+
-+         while (pos < end)
-+         {
-+            VCHIQ_HEADER_T *header = (VCHIQ_HEADER_T *)(data + pos);
-+            int msgid = header->msgid;
-+            int port = VCHIQ_MSG_DSTPORT(msgid);
-+            if (port == service->localport)
-+            {
-+               if (msgid & VCHIQ_MSGID_CLAIMED)
-+               {
-+                  header->msgid = msgid & ~VCHIQ_MSGID_CLAIMED;
-+                  vcos_log_info("  fsi - hdr %x", (unsigned int)header);
-+                  release_slot(state, slot_info);
-+               }
-+            }
-+            pos += calc_stride(header->size);
-+         }
-+      }
-+   }
-+
-+   vcos_assert(state->services[service->localport] == service);
-+   vchiq_set_service_state(service, VCHIQ_SRVSTATE_FREE);
-+   state->services[service->localport] = NULL;
-+   vcos_free(service);
-+   vcos_mutex_unlock(&state->mutex);
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance)
-+{
-+   int i;
-+
-+   /* Find all services registered to this client and enable them. */
-+   for (i = 0; i < state->unused_service; i++)
-+   {
-+      VCHIQ_SERVICE_T *service = state->services[i];
-+      if (service && (service->instance == instance)) {
-+         if (service->srvstate == VCHIQ_SRVSTATE_HIDDEN)
-+            vchiq_set_service_state(service,
-+               VCHIQ_SRVSTATE_LISTENING);
-+      }
-+   }
-+
-+   if (state->conn_state == VCHIQ_CONNSTATE_DISCONNECTED) {
-+      if (queue_message(state, NULL,
-+         VCHIQ_MAKE_MSG(VCHIQ_MSG_CONNECT, 0, 0), NULL, 0,
-+         0, 1) == VCHIQ_RETRY)
-+         return VCHIQ_RETRY;
-+      vcos_event_wait(&state->connect);
-+
-+      vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED);
-+   }
-+
-+   return VCHIQ_SUCCESS;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_shutdown_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance)
-+{
-+   VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
-+   int i;
-+
-+   /* Find all services registered to this client and close them. */
-+   for (i = 0; i < state->unused_service; i++)
-+   {
-+      VCHIQ_SERVICE_T *service = state->services[i];
-+      if (service && (service->instance == instance) &&
-+         ((service->srvstate == VCHIQ_SRVSTATE_OPEN) ||
-+         (service->srvstate == VCHIQ_SRVSTATE_LISTENING)))
-+      {
-+         status = vchiq_remove_service(&service->base);
-+         if (status != VCHIQ_SUCCESS)
-+            break;
-+      }
-+   }
-+
-+   return status;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_pause_internal(VCHIQ_STATE_T *state)
-+{
-+   VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
-+
-+   switch (state->conn_state)
-+   {
-+   case VCHIQ_CONNSTATE_CONNECTED:
-+      /* Request a pause */
-+      vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSING);
-+      request_poll(state, NULL, 0);
-+      break;
-+   case VCHIQ_CONNSTATE_PAUSED:
-+      break;
-+   default:
-+      status = VCHIQ_ERROR;
-+      VCHIQ_STATS_INC(state, error_count);
-+      break;
-+   }
-+
-+   return status;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_resume_internal(VCHIQ_STATE_T *state)
-+{
-+   VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
-+
-+   if (state->conn_state == VCHIQ_CONNSTATE_PAUSED)
-+   {
-+      vchiq_set_conn_state(state, VCHIQ_CONNSTATE_RESUMING);
-+      request_poll(state, NULL, 0);
-+   }
-+   else
-+   {
-+      status = VCHIQ_ERROR;
-+      VCHIQ_STATS_INC(state, error_count);
-+   }
-+
-+   return status;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_close_service(VCHIQ_SERVICE_HANDLE_T handle)
-+{
-+   /* Unregister the service */
-+   VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *) handle;
-+   VCHIQ_STATUS_T status = VCHIQ_ERROR;
-+
-+   if (service == NULL)
-+      return VCHIQ_ERROR;
-+
-+   vcos_log_info("%d: close_service:%d", service->state->id, service->localport);
-+
-+   if (service->public_fourcc != VCHIQ_FOURCC_INVALID)
-+   {
-+      if (service->srvstate == VCHIQ_SRVSTATE_CLOSEWAIT)
-+      {
-+         /* This is a non-auto-close server */
-+         vchiq_set_service_state(service, VCHIQ_SRVSTATE_LISTENING);
-+         status = VCHIQ_SUCCESS;
-+      }
-+   }
-+   else
-+   {
-+      /* For clients, make it an alias of vchiq_remove_service */
-+      status = vchiq_remove_service(handle);
-+   }
-+
-+   return status;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T handle)
-+{
-+   /* Unregister the service */
-+   VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *) handle;
-+   VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
-+
-+   if (service == NULL)
-+      return VCHIQ_ERROR;
-+
-+   vcos_log_info("%d: remove_service:%d", service->state->id, service->localport);
-+
-+   switch (service->srvstate)
-+   {
-+   case VCHIQ_SRVSTATE_OPENING:
-+   case VCHIQ_SRVSTATE_OPEN:
-+      /* Mark the service for termination by the slot handler */
-+      request_poll(service->state, service, VCHIQ_POLL_TERMINATE);
-+
-+      /* Drop through... */
-+   case VCHIQ_SRVSTATE_CLOSESENT:
-+   case VCHIQ_SRVSTATE_CLOSING:
-+      while ((service->srvstate != VCHIQ_SRVSTATE_CLOSEWAIT) &&
-+         (service->srvstate != VCHIQ_SRVSTATE_LISTENING))
-+      {
-+         if (vcos_event_wait(&service->remove_event) != VCOS_SUCCESS) {
-+            status = VCHIQ_RETRY;
-+            break;
-+         }
-+      }
-+      break;
-+
-+   default:
-+      break;
-+   }
-+
-+   if (status == VCHIQ_SUCCESS) {
-+      if (service->srvstate == VCHIQ_SRVSTATE_OPEN)
-+         status = VCHIQ_ERROR;
-+      else
-+      {
-+         service->instance = NULL;
-+         vchiq_free_service_internal(service);
-+      }
-+   }
-+
-+   return status;
-+}
-+
-+
-+VCHIQ_STATUS_T
-+vchiq_bulk_transfer(VCHIQ_SERVICE_T *service,
-+   VCHI_MEM_HANDLE_T memhandle, void *offset, int size, void *userdata,
-+   VCHIQ_BULK_MODE_T mode, VCHIQ_BULK_DIR_T dir)
-+{
-+   VCHIQ_BULK_QUEUE_T *queue = (dir == VCHIQ_BULK_TRANSMIT) ?
-+      &service->bulk_tx : &service->bulk_rx;
-+   VCHIQ_BULK_T *bulk;
-+   VCHIQ_STATE_T *state;
-+   BULK_WAITER_T bulk_waiter;
-+   const char dir_char = (dir == VCHIQ_BULK_TRANSMIT) ? 't' : 'r';
-+   const int dir_msgtype = (dir == VCHIQ_BULK_TRANSMIT) ? VCHIQ_MSG_BULK_TX : VCHIQ_MSG_BULK_RX;
-+   VCHIQ_STATUS_T status = VCHIQ_ERROR;
-+
-+   if ((service == NULL) ||
-+       ((memhandle == VCHI_MEM_HANDLE_INVALID) && (offset == NULL)))
-+      return VCHIQ_ERROR;
-+
-+   state = service->state;
-+
-+   if (service->srvstate != VCHIQ_SRVSTATE_OPEN)
-+      return VCHIQ_ERROR;  /* Must be connected */
-+
-+   if (vcos_mutex_lock(&service->bulk_mutex) != VCOS_SUCCESS)
-+      return VCHIQ_RETRY;
-+
-+   if (queue->local_insert == queue->remove + VCHIQ_NUM_SERVICE_BULKS)
-+   {
-+      VCHIQ_SERVICE_STATS_INC(service, bulk_stalls);
-+      do {
-+         vcos_mutex_unlock(&service->bulk_mutex);
-+         if (vcos_event_wait(&service->bulk_remove_event) != VCOS_SUCCESS)
-+            return VCHIQ_RETRY;
-+         if (vcos_mutex_lock(&service->bulk_mutex) != VCOS_SUCCESS)
-+            return VCHIQ_RETRY;
-+      } while (queue->local_insert == queue->remove + VCHIQ_NUM_SERVICE_BULKS);
-+   }
-+
-+   bulk = &queue->bulks[BULK_INDEX(queue->local_insert)];
-+
-+   if (mode == VCHIQ_BULK_MODE_BLOCKING)
-+   {
-+      vcos_event_create(&bulk_waiter.event, "bulk_waiter");
-+      bulk_waiter.actual = 0;
-+      userdata = &bulk_waiter;
-+   }
-+
-+   bulk->mode = mode;
-+   bulk->dir = dir;
-+   bulk->userdata = userdata;
-+   bulk->size = size;
-+   bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED;
-+
-+   if (vchiq_prepare_bulk_data(bulk, memhandle, offset, size, dir) != VCHIQ_SUCCESS)
-+   {
-+      goto error_exit;
-+   }
-+
-+   vcos_log_info("%d: bt (%d->%d) %cx %x@%x %x", state->id,
-+      service->localport, service->remoteport, dir_char,
-+      size, (unsigned int)bulk->data, (unsigned int)userdata);
-+
-+   if (state->is_master)
-+   {
-+      queue->local_insert++;
-+      if (resolve_bulks(service, queue))
-+         request_poll(state, service, (dir == VCHIQ_BULK_TRANSMIT) ?
-+            VCHIQ_POLL_TXNOTIFY : VCHIQ_POLL_RXNOTIFY);
-+   }
-+   else
-+   {
-+      int payload[2] = { (int)bulk->data, bulk->size };
-+      VCHIQ_ELEMENT_T element = { payload, sizeof(payload) };
-+
-+      if (queue_message(state, NULL,
-+         VCHIQ_MAKE_MSG(dir_msgtype,
-+            service->localport, service->remoteport),
-+         &element, 1, sizeof(payload), 1) != VCHIQ_SUCCESS)
-+      {
-+         vchiq_complete_bulk(bulk);
-+         goto error_exit;
-+      }
-+      queue->local_insert++;
-+      queue->remote_insert++;
-+   }
-+
-+   vcos_mutex_unlock(&service->bulk_mutex);
-+ 
-+   vcos_log_trace("%d: bt:%d %cx li=%x ri=%x p=%x", state->id,
-+      service->localport, dir_char,
-+      queue->local_insert, queue->remote_insert, queue->process);
-+
-+   status = VCHIQ_SUCCESS;
-+
-+   if (mode == VCHIQ_BULK_MODE_BLOCKING)
-+   {
-+      if (vcos_event_wait(&bulk_waiter.event) != VCOS_SUCCESS)
-+      {
-+         vcos_log_info("bulk wait interrupted");
-+         /* Stop notify_bulks signalling a non-existent waiter */
-+         bulk->userdata = NULL;
-+         status = VCHIQ_ERROR;
-+      }
-+      else if (bulk_waiter.actual == VCHIQ_BULK_ACTUAL_ABORTED)
-+         status = VCHIQ_ERROR;
-+
-+      vcos_event_delete(&bulk_waiter.event);
-+   }
-+
-+   return status;
-+
-+error_exit:
-+   if (mode == VCHIQ_BULK_MODE_BLOCKING)
-+      vcos_event_delete(&bulk_waiter.event);
-+   vcos_mutex_unlock(&service->bulk_mutex);
-+
-+   return status;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle,
-+   const void *data, int size, void *userdata)
-+{
-+   return vchiq_bulk_transfer((VCHIQ_SERVICE_T *)handle,
-+      VCHI_MEM_HANDLE_INVALID, (void *)data, size, userdata,
-+      VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_TRANSMIT);
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_queue_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data, int size,
-+   void *userdata)
-+{
-+   return vchiq_bulk_transfer((VCHIQ_SERVICE_T *)handle,
-+      VCHI_MEM_HANDLE_INVALID, data, size, userdata,
-+      VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_RECEIVE);
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_queue_bulk_transmit_handle(VCHIQ_SERVICE_HANDLE_T handle,
-+   VCHI_MEM_HANDLE_T memhandle, const void *offset, int size, void *userdata)
-+{
-+   return vchiq_bulk_transfer((VCHIQ_SERVICE_T *)handle,
-+      memhandle, (void *)offset, size, userdata,
-+      VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_TRANSMIT);
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_queue_bulk_receive_handle(VCHIQ_SERVICE_HANDLE_T handle,
-+   VCHI_MEM_HANDLE_T memhandle, void *offset, int size, void *userdata)
-+{
-+   return vchiq_bulk_transfer((VCHIQ_SERVICE_T *)handle,
-+      memhandle, offset, size, userdata,
-+      VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_RECEIVE);
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle, const void *data, int size,
-+   void *userdata, VCHIQ_BULK_MODE_T mode)
-+{
-+   return vchiq_bulk_transfer((VCHIQ_SERVICE_T *)handle,
-+      VCHI_MEM_HANDLE_INVALID, (void *)data, size, userdata,
-+      mode, VCHIQ_BULK_TRANSMIT);
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data, int size,
-+   void *userdata, VCHIQ_BULK_MODE_T mode)
-+{
-+   return vchiq_bulk_transfer((VCHIQ_SERVICE_T *)handle,
-+      VCHI_MEM_HANDLE_INVALID, data, size, userdata,
-+      mode, VCHIQ_BULK_RECEIVE);
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_bulk_transmit_handle(VCHIQ_SERVICE_HANDLE_T handle,
-+   VCHI_MEM_HANDLE_T memhandle, const void *offset, int size, void *userdata,
-+   VCHIQ_BULK_MODE_T mode)
-+{
-+   return vchiq_bulk_transfer((VCHIQ_SERVICE_T *)handle,
-+      memhandle, (void *)offset, size, userdata,
-+      mode, VCHIQ_BULK_TRANSMIT);
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_bulk_receive_handle(VCHIQ_SERVICE_HANDLE_T handle,
-+   VCHI_MEM_HANDLE_T memhandle, void *offset, int size, void *userdata,
-+   VCHIQ_BULK_MODE_T mode)
-+{
-+   return vchiq_bulk_transfer((VCHIQ_SERVICE_T *)handle,
-+      memhandle, offset, size, userdata,
-+      mode, VCHIQ_BULK_RECEIVE);
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T handle,
-+   const VCHIQ_ELEMENT_T *elements, int count)
-+{
-+   VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *) handle;
-+
-+   unsigned int size = 0;
-+   unsigned int i;
-+
-+   if ((service == NULL) ||
-+      (service->srvstate != VCHIQ_SRVSTATE_OPEN))
-+      return VCHIQ_ERROR;
-+
-+   for (i = 0; i < (unsigned int)count; i++)
-+   {
-+      if (elements[i].size)
-+      {
-+         if (elements[i].data == NULL)
-+         {
-+            VCHIQ_SERVICE_STATS_INC(service, error_count);
-+            return VCHIQ_ERROR;
-+         }
-+         size += elements[i].size;
-+      }
-+   }
-+
-+   if (size > VCHIQ_MAX_MSG_SIZE)
-+   {
-+      VCHIQ_SERVICE_STATS_INC(service, error_count);
-+      return VCHIQ_ERROR;
-+   }
-+
-+   return queue_message(service->state, service,
-+            VCHIQ_MAKE_MSG(VCHIQ_MSG_DATA, service->localport,
-+               service->remoteport), elements, count, size, 1);
-+}
-+
-+void
-+vchiq_release_message(VCHIQ_SERVICE_HANDLE_T handle, VCHIQ_HEADER_T *header)
-+{
-+   VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
-+   VCHIQ_STATE_T *state;
-+   int slot_index;
-+   int msgid;
-+
-+   if (service == NULL)
-+      return;
-+
-+   state = service->state;
-+
-+   slot_index = SLOT_INDEX_FROM_DATA(state, (void *)header);
-+
-+   if ((slot_index >= state->remote->slot_first) &&
-+      (slot_index <= state->remote->slot_last) &&
-+      ((msgid = header->msgid) & VCHIQ_MSGID_CLAIMED))
-+   {
-+      VCHIQ_SLOT_INFO_T *slot_info = SLOT_INFO_FROM_INDEX(state, slot_index);
-+
-+      /* Rewrite the message header to prevent a double release */
-+      header->msgid = msgid & ~VCHIQ_MSGID_CLAIMED;
-+
-+      release_slot(state, slot_info);
-+   }
-+}
-+
-+int
-+vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T handle)
-+{
-+   VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
-+   return service ? service->client_id : 0;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_get_config(VCHIQ_INSTANCE_T instance,
-+   int config_size, VCHIQ_CONFIG_T *pconfig)
-+{
-+   VCHIQ_CONFIG_T config;
-+
-+   vcos_unused(instance);
-+
-+   config.max_msg_size           = VCHIQ_MAX_MSG_SIZE;
-+   config.bulk_threshold         = VCHIQ_MAX_MSG_SIZE;
-+   config.max_outstanding_bulks  = VCHIQ_NUM_SERVICE_BULKS;
-+   config.max_services           = VCHIQ_MAX_SERVICES;
-+   config.version                = VCHIQ_VERSION;
-+   config.version_min            = VCHIQ_VERSION_MIN;
-+
-+   if (config_size > sizeof(VCHIQ_CONFIG_T))
-+      return VCHIQ_ERROR;
-+
-+   memcpy(pconfig, &config, vcos_min(config_size, sizeof(VCHIQ_CONFIG_T)));
-+
-+   return VCHIQ_SUCCESS;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T handle,
-+   VCHIQ_SERVICE_OPTION_T option, int value)
-+{
-+   VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
-+   VCHIQ_STATUS_T status = VCHIQ_ERROR;
-+
-+   if (service)
-+   {
-+      switch (option)
-+      {
-+      case VCHIQ_SERVICE_OPTION_AUTOCLOSE:
-+         service->auto_close = value;
-+         status = VCHIQ_SUCCESS;
-+         break;
-+
-+      default:
-+         break;
-+      }
-+   }
-+
-+   return status;
-+}
-+
-+void
-+vchiq_dump_shared_state(void *dump_context, VCHIQ_STATE_T *state,
-+   VCHIQ_SHARED_STATE_T *shared, const char *label)
-+{
-+   static const char *const debug_names[] =
-+   {
-+      "<entries>",
-+      "SLOT_HANDLER_COUNT",
-+      "SLOT_HANDLER_LINE",
-+      "PARSE_LINE",
-+      "PARSE_HEADER",
-+      "PARSE_MSGID",
-+      "AWAIT_COMPLETION_LINE",
-+      "DEQUEUE_MESSAGE_LINE",
-+      "SERVICE_CALLBACK_LINE",
-+      "MSG_QUEUE_FULL_COUNT",
-+      "COMPLETION_QUEUE_FULL_COUNT"
-+   };
-+   int i;
-+
-+   char buf[80];
-+   int len;
-+   len = vcos_snprintf(buf, sizeof(buf),
-+      "  %s: slots %d-%d tx_pos=%x recycle=%x",
-+      label, shared->slot_first, shared->slot_last,
-+      shared->tx_pos, shared->slot_queue_recycle);
-+   vchiq_dump(dump_context, buf, len + 1);
-+
-+   len = vcos_snprintf(buf, sizeof(buf),
-+      "    Slots claimed:"); 
-+   vchiq_dump(dump_context, buf, len + 1);
-+
-+   for (i = shared->slot_first; i <= shared->slot_last; i++)
-+   {
-+      VCHIQ_SLOT_INFO_T slot_info = *SLOT_INFO_FROM_INDEX(state, i);
-+      if (slot_info.use_count != slot_info.release_count)
-+      {
-+         len = vcos_snprintf(buf, sizeof(buf),
-+            "      %d: %d/%d", i, slot_info.use_count, slot_info.release_count);
-+         vchiq_dump(dump_context, buf, len + 1);
-+      }
-+   }
-+
-+   for (i = 1; i < shared->debug[DEBUG_ENTRIES]; i++)
-+   {
-+      len = vcos_snprintf(buf, sizeof(buf), "    DEBUG: %s = %d(%x)",
-+         debug_names[i], shared->debug[i], shared->debug[i]);
-+      vchiq_dump(dump_context, buf, len + 1);
-+   }
-+}
-+
-+void
-+vchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state)
-+{
-+   char buf[80];
-+   int len;
-+   int i;
-+
-+   len = vcos_snprintf(buf, sizeof(buf), "State %d: %s", state->id,
-+      conn_state_names[state->conn_state]);
-+   vchiq_dump(dump_context, buf, len + 1);
-+
-+   len = vcos_snprintf(buf, sizeof(buf),
-+      "  tx_pos=%x(@%x), rx_pos=%x(@%x)",
-+      state->id, state->local->tx_pos,
-+      (uint32_t)state->tx_data + (state->local_tx_pos & VCHIQ_SLOT_MASK),
-+      state->rx_pos,
-+      (uint32_t)state->rx_data + (state->rx_pos & VCHIQ_SLOT_MASK));
-+   vchiq_dump(dump_context, buf, len + 1);
-+
-+   len = vcos_snprintf(buf, sizeof(buf),
-+      "  Version: %d (min %d)",
-+      VCHIQ_VERSION, VCHIQ_VERSION_MIN);
-+   vchiq_dump(dump_context, buf, len + 1);
-+
-+   if (VCHIQ_ENABLE_STATS)
-+   {
-+      len = vcos_snprintf(buf, sizeof(buf),
-+         "  Stats: ctrl_tx_count=%d, ctrl_rx_count=%d, error_count=%d",
-+         state->stats.ctrl_tx_count, state->stats.ctrl_rx_count,
-+         state->stats.slot_stalls);
-+      vchiq_dump(dump_context, buf, len + 1);
-+   }
-+
-+   len = vcos_snprintf(buf, sizeof(buf),
-+      "  Slots: %d available, %d recyclable, %d stalls",
-+      state->slot_queue_available - SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos),
-+      state->local->slot_queue_recycle - state->slot_queue_available,
-+      state->stats.slot_stalls);
-+   vchiq_dump(dump_context, buf, len + 1);
-+
-+   vchiq_dump_platform_state(dump_context);
-+
-+   vchiq_dump_shared_state(dump_context, state, state->local, "Local");
-+   vchiq_dump_shared_state(dump_context, state, state->remote, "Remote");
-+
-+   vchiq_dump_platform_instances(dump_context);
-+
-+   for (i = 0; i < state->unused_service; i++) {
-+      VCHIQ_SERVICE_T *service = state->services[i];
-+
-+      if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE))
-+         vchiq_dump_service_state(dump_context, service);
-+   }
-+}
-+
-+void
-+vchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service)
-+{
-+   char buf[80];
-+   int len;
-+
-+   len = vcos_snprintf(buf, sizeof(buf), "Service %d: %s",
-+      service->localport, srvstate_names[service->srvstate]);
-+
-+   if (service->srvstate != VCHIQ_SRVSTATE_FREE)
-+   {
-+      char remoteport[30];
-+      VCHIQ_SERVICE_QUOTA_T *service_quota =
-+         &service->state->service_quotas[service->localport];
-+      int fourcc = service->base.fourcc;
-+      if (service->remoteport != VCHIQ_PORT_FREE)
-+      {
-+         int len2 = vcos_snprintf(remoteport, sizeof(remoteport), "%d",
-+            service->remoteport);
-+         if (service->public_fourcc != VCHIQ_FOURCC_INVALID)
-+            vcos_snprintf(remoteport + len2, sizeof(remoteport) - len2,
-+               " (client %x)", service->client_id);
-+      }
-+      else
-+         vcos_strcpy(remoteport, "n/a");
-+
-+      len += vcos_snprintf(buf + len, sizeof(buf) - len,
-+         " '%c%c%c%c' remote %s (slot use %d/%d)",
-+         VCHIQ_FOURCC_AS_4CHARS(fourcc),
-+         remoteport,
-+         service_quota->slot_use_count,
-+         service_quota->slot_quota);
-+
-+      if (VCHIQ_ENABLE_STATS)
-+      {
-+         vchiq_dump(dump_context, buf, len + 1);
-+
-+         len = vcos_snprintf(buf, sizeof(buf),
-+            "  Ctrl: tx_count=%d, tx_bytes=%" PRIu64 ", rx_count=%d, rx_bytes=%" PRIu64,
-+            service->stats.ctrl_tx_count, service->stats.ctrl_tx_bytes,
-+            service->stats.ctrl_rx_count, service->stats.ctrl_rx_bytes);
-+         vchiq_dump(dump_context, buf, len + 1);
-+
-+         len = vcos_snprintf(buf, sizeof(buf),
-+            "  Bulk: tx_count=%d, tx_bytes=%" PRIu64 ", rx_count=%d, rx_bytes=%" PRIu64,
-+            service->stats.bulk_tx_count, service->stats.bulk_tx_bytes,
-+            service->stats.bulk_rx_count, service->stats.bulk_rx_bytes);
-+         vchiq_dump(dump_context, buf, len + 1);
-+
-+         len = vcos_snprintf(buf, sizeof(buf),
-+            "  %d quota stalls, %d slot stalls, %d bulk stalls, %d aborted, %d errors",
-+            service->stats.quota_stalls, service->stats.slot_stalls,
-+            service->stats.bulk_stalls, service->stats.bulk_aborted_count,
-+            service->stats.error_count);
-+       }
-+   }
-+
-+   vchiq_dump(dump_context, buf, len + 1);
-+
-+   vchiq_dump_platform_service_state(dump_context, service);
-+}
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h
-@@ -0,0 +1,480 @@
-+/*
-+ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#ifndef VCHIQ_CORE_H
-+#define VCHIQ_CORE_H
-+
-+#include "vchiq_cfg.h"
-+
-+#include "vchiq.h"
-+
-+#define IS_POW2(x) (x && ((x & (x - 1)) == 0))
-+
-+/* Ensure that the slot size and maximum number of slots are powers of 2 */
-+vcos_static_assert(IS_POW2(VCHIQ_SLOT_SIZE));
-+vcos_static_assert(IS_POW2(VCHIQ_MAX_SLOTS));
-+vcos_static_assert(IS_POW2(VCHIQ_MAX_SLOTS_PER_SIDE));
-+
-+#define VCHIQ_SLOT_MASK        (VCHIQ_SLOT_SIZE - 1)
-+#define VCHIQ_SLOT_QUEUE_MASK  (VCHIQ_MAX_SLOTS_PER_SIDE - 1)
-+#define VCHIQ_SLOT_ZERO_SLOTS  ((sizeof(VCHIQ_SLOT_ZERO_T) + \
-+   VCHIQ_SLOT_SIZE - 1) / VCHIQ_SLOT_SIZE)
-+
-+#define VCHIQ_MSG_PADDING              0  // -
-+#define VCHIQ_MSG_CONNECT              1  // -
-+#define VCHIQ_MSG_OPEN                 2  // + (srcport, -), fourcc, client_id
-+#define VCHIQ_MSG_OPENACK              3  // + (srcport, dstport)
-+#define VCHIQ_MSG_CLOSE                4  // + (srcport, dstport)
-+#define VCHIQ_MSG_DATA                 5  // + (srcport, dstport)
-+#define VCHIQ_MSG_BULK_RX              6  // + (srcport, dstport), data, size
-+#define VCHIQ_MSG_BULK_TX              7  // + (srcport, dstport), data, size
-+#define VCHIQ_MSG_BULK_RX_DONE         8  // + (srcport, dstport), actual
-+#define VCHIQ_MSG_BULK_TX_DONE         9  // + (srcport, dstport), actual
-+#define VCHIQ_MSG_PAUSE               10  // -
-+#define VCHIQ_MSG_RESUME              11  // -
-+
-+#define VCHIQ_PORT_MAX                 (VCHIQ_MAX_SERVICES - 1)
-+#define VCHIQ_PORT_FREE                0x1000
-+#define VCHIQ_PORT_IS_VALID(port)      (port < VCHIQ_PORT_FREE)
-+#define VCHIQ_MAKE_MSG(type,srcport,dstport)      ((type<<24) | (srcport<<12) | (dstport<<0))
-+#define VCHIQ_MSG_TYPE(msgid)          ((unsigned int)msgid >> 24)
-+#define VCHIQ_MSG_SRCPORT(msgid)       (unsigned short)(((unsigned int)msgid >> 12) & 0xfff)
-+#define VCHIQ_MSG_DSTPORT(msgid)       ((unsigned short)msgid & 0xfff)
-+
-+#define VCHIQ_FOURCC_AS_4CHARS(fourcc)        \
-+   ((fourcc) >> 24) & 0xff, \
-+   ((fourcc) >> 16) & 0xff, \
-+   ((fourcc) >>  8) & 0xff, \
-+   ((fourcc)      ) & 0xff
-+
-+/* Ensure the fields are wide enough */
-+vcos_static_assert(VCHIQ_MSG_SRCPORT(VCHIQ_MAKE_MSG(0,0,VCHIQ_PORT_MAX)) == 0);
-+vcos_static_assert(VCHIQ_MSG_TYPE(VCHIQ_MAKE_MSG(0,VCHIQ_PORT_MAX,0)) == 0);
-+vcos_static_assert((unsigned int)VCHIQ_PORT_MAX < (unsigned int)VCHIQ_PORT_FREE);
-+
-+#define VCHIQ_MSGID_PADDING            VCHIQ_MAKE_MSG(VCHIQ_MSG_PADDING,0,0)
-+#define VCHIQ_MSGID_CLAIMED            0x40000000
-+
-+#define VCHIQ_FOURCC_INVALID           0x00000000
-+#define VCHIQ_FOURCC_IS_LEGAL(fourcc)  (fourcc != VCHIQ_FOURCC_INVALID)
-+
-+#define VCHIQ_BULK_ACTUAL_ABORTED -1
-+
-+typedef uint32_t BITSET_T;
-+
-+vcos_static_assert((sizeof(BITSET_T) * 8) == 32);
-+
-+#define BITSET_SIZE(b)        ((b + 31) >> 5)
-+#define BITSET_WORD(b)        (b >> 5)
-+#define BITSET_BIT(b)         (1 << (b & 31))
-+#define BITSET_ZERO(bs)       memset(bs, 0, sizeof(bs))
-+#define BITSET_IS_SET(bs, b)  (bs[BITSET_WORD(b)] & BITSET_BIT(b))
-+#define BITSET_SET(bs, b)     (bs[BITSET_WORD(b)] |= BITSET_BIT(b))
-+#define BITSET_CLR(bs, b)     (bs[BITSET_WORD(b)] &= ~BITSET_BIT(b))
-+
-+#if VCHIQ_ENABLE_STATS
-+#define VCHIQ_STATS_INC(state, stat) (state->stats. stat ++)
-+#define VCHIQ_SERVICE_STATS_INC(service, stat) (service->stats. stat ++)
-+#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) (service->stats. stat += addend)
-+#else
-+#define VCHIQ_STATS_INC(state, stat) ((void)0)
-+#define VCHIQ_SERVICE_STATS_INC(service, stat) ((void)0)
-+#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) ((void)0)
-+#endif
-+
-+enum
-+{
-+   DEBUG_ENTRIES,
-+#if VCHIQ_ENABLE_DEBUG
-+   DEBUG_SLOT_HANDLER_COUNT,
-+   DEBUG_SLOT_HANDLER_LINE,
-+   DEBUG_PARSE_LINE,
-+   DEBUG_PARSE_HEADER,
-+   DEBUG_PARSE_MSGID,
-+   DEBUG_AWAIT_COMPLETION_LINE,
-+   DEBUG_DEQUEUE_MESSAGE_LINE,
-+   DEBUG_SERVICE_CALLBACK_LINE,
-+   DEBUG_MSG_QUEUE_FULL_COUNT,
-+   DEBUG_COMPLETION_QUEUE_FULL_COUNT,
-+#endif
-+   DEBUG_MAX
-+};
-+
-+#if VCHIQ_ENABLE_DEBUG
-+
-+#define DEBUG_INITIALISE(local) volatile int *debug_ptr = (local)->debug;
-+#define DEBUG_TRACE(d) debug_ptr[DEBUG_ ## d] = __LINE__
-+#define DEBUG_VALUE(d,v) debug_ptr[DEBUG_ ## d] = (v)
-+#define DEBUG_COUNT(d) debug_ptr[DEBUG_ ## d]++
-+
-+#else /* VCHIQ_ENABLE_DEBUG */
-+
-+#define DEBUG_INITIALISE(local)
-+#define DEBUG_TRACE(d)
-+#define DEBUG_VALUE(d,v)
-+#define DEBUG_COUNT(d)
-+
-+#endif /* VCHIQ_ENABLE_DEBUG */
-+
-+typedef enum
-+{
-+   VCHIQ_CONNSTATE_DISCONNECTED,
-+   VCHIQ_CONNSTATE_CONNECTED,
-+   VCHIQ_CONNSTATE_PAUSING,
-+   VCHIQ_CONNSTATE_PAUSE_SENT,
-+   VCHIQ_CONNSTATE_PAUSED,
-+   VCHIQ_CONNSTATE_RESUMING
-+} VCHIQ_CONNSTATE_T;
-+
-+enum
-+{
-+   VCHIQ_SRVSTATE_FREE,
-+   VCHIQ_SRVSTATE_HIDDEN,
-+   VCHIQ_SRVSTATE_LISTENING,
-+   VCHIQ_SRVSTATE_OPENING,
-+   VCHIQ_SRVSTATE_OPEN,
-+   VCHIQ_SRVSTATE_CLOSESENT,
-+   VCHIQ_SRVSTATE_CLOSING,
-+   VCHIQ_SRVSTATE_CLOSEWAIT
-+};
-+
-+enum
-+{
-+   VCHIQ_POLL_TERMINATE,
-+   VCHIQ_POLL_TXNOTIFY,
-+   VCHIQ_POLL_RXNOTIFY,
-+   VCHIQ_POLL_COUNT
-+};
-+
-+typedef enum
-+{
-+   VCHIQ_BULK_TRANSMIT,
-+   VCHIQ_BULK_RECEIVE
-+} VCHIQ_BULK_DIR_T;
-+
-+typedef struct vchiq_bulk_struct {
-+   short mode;
-+   short dir;
-+   void *userdata;
-+   VCHI_MEM_HANDLE_T handle;
-+   void *data;
-+   int size;
-+   void *remote_data;
-+   int remote_size;
-+   int actual;
-+} VCHIQ_BULK_T;
-+
-+typedef struct vchiq_bulk_queue_struct {
-+   int local_insert;  /* Where to insert the next local bulk */
-+   int remote_insert; /* Where to insert the next remote bulk (master) */
-+   int process;       /* Bulk to transfer next */
-+   int remote_notify; /* Bulk to notify the remote client of next (master) */
-+   int remove;        /* Bulk to notify the local client of, and remove, next */
-+   VCHIQ_BULK_T bulks[VCHIQ_NUM_SERVICE_BULKS];
-+} VCHIQ_BULK_QUEUE_T;
-+
-+typedef struct remote_event_struct {
-+   volatile int armed;
-+   volatile int fired;
-+   VCOS_EVENT_T * event;
-+} REMOTE_EVENT_T;
-+
-+typedef struct vchiq_state_struct VCHIQ_STATE_T;
-+
-+typedef struct vchiq_slot_struct {
-+   char data[VCHIQ_SLOT_SIZE];
-+} VCHIQ_SLOT_T;
-+
-+typedef struct vchiq_slot_info_struct {
-+   /* Use two counters rather than one to avoid the need for a mutex. */
-+   volatile short use_count;
-+   volatile short release_count;
-+} VCHIQ_SLOT_INFO_T;
-+
-+typedef struct vchiq_service_struct {
-+   VCHIQ_SERVICE_BASE_T base;
-+   volatile int srvstate;
-+   unsigned int localport;
-+   unsigned int remoteport;
-+   int public_fourcc;
-+   int client_id;
-+   int auto_close;
-+   VCOS_ATOMIC_FLAGS_T poll_flags;
-+   short version;
-+   short version_min;
-+
-+   VCHIQ_STATE_T *state;
-+   VCHIQ_INSTANCE_T instance;
-+
-+   int service_use_count;
-+
-+   VCHIQ_BULK_QUEUE_T bulk_tx;
-+   VCHIQ_BULK_QUEUE_T bulk_rx;
-+
-+   VCOS_EVENT_T remove_event;
-+   VCOS_EVENT_T bulk_remove_event;
-+   VCOS_MUTEX_T bulk_mutex;
-+
-+   struct service_stats_struct
-+   {
-+      int quota_stalls;
-+      int slot_stalls;
-+      int bulk_stalls;
-+      int error_count;
-+      int ctrl_tx_count;
-+      int ctrl_rx_count;
-+      int bulk_tx_count;
-+      int bulk_rx_count;
-+      int bulk_aborted_count;
-+      uint64_t ctrl_tx_bytes;
-+      uint64_t ctrl_rx_bytes;
-+      uint64_t bulk_tx_bytes;
-+      uint64_t bulk_rx_bytes;
-+   } stats;
-+} VCHIQ_SERVICE_T;
-+
-+/* The quota information is outside VCHIQ_SERVICE_T so that it can be
-+   statically allocated, since for accounting reasons a service's slot
-+   usage is carried over between users of the same port number.
-+ */
-+typedef struct vchiq_service_quota_struct {
-+   int slot_quota;
-+   int slot_use_count;
-+   VCOS_EVENT_T quota_event;
-+   int previous_tx_index;
-+} VCHIQ_SERVICE_QUOTA_T;
-+
-+typedef struct vchiq_shared_state_struct {
-+
-+   /* A non-zero value here indicates that the content is valid. */
-+   int initialised;
-+
-+   /* The first and last (inclusive) slots allocated to the owner. */
-+   int slot_first;
-+   int slot_last;
-+
-+   /* Signalling this event indicates that owner's slot handler thread should
-+      run. */
-+   REMOTE_EVENT_T trigger;
-+
-+   /* Indicates the byte position within the stream where the next message
-+      will be written. The least significant bits are an index into the slot.
-+      The next bits are the index of the slot in slot_queue. */
-+   volatile int tx_pos;
-+
-+   /* This event should be signalled when a slot is recycled. */
-+   REMOTE_EVENT_T recycle;
-+
-+   /* The slot_queue index where the next recycled slot will be written. */
-+   volatile int slot_queue_recycle;
-+
-+   /* A circular buffer of slot indexes. */
-+   int slot_queue[VCHIQ_MAX_SLOTS_PER_SIDE];
-+
-+   /* Debugging state */
-+   volatile int debug[DEBUG_MAX];
-+} VCHIQ_SHARED_STATE_T;
-+
-+typedef struct vchiq_slot_zero_struct {
-+   int magic;
-+   short version;
-+   short version_min;
-+   int slot_zero_size;
-+   int slot_size;
-+   int max_slots;
-+   int max_slots_per_side;
-+   int platform_data[2];
-+   VCHIQ_SHARED_STATE_T master;
-+   VCHIQ_SHARED_STATE_T slave;
-+   VCHIQ_SLOT_INFO_T slots[VCHIQ_MAX_SLOTS];
-+} VCHIQ_SLOT_ZERO_T;
-+
-+struct vchiq_state_struct {
-+   int id;
-+   int initialised;
-+   VCHIQ_CONNSTATE_T conn_state;
-+   int is_master;
-+
-+   VCHIQ_SHARED_STATE_T *local;
-+   VCHIQ_SHARED_STATE_T *remote;
-+   VCHIQ_SLOT_T *slot_data;
-+
-+   int default_slot_quota;
-+
-+   VCOS_EVENT_T connect;      // event indicating connect message received
-+   VCOS_MUTEX_T mutex;        // mutex protecting services
-+   VCHIQ_INSTANCE_T *instance;
-+
-+   VCOS_THREAD_T slot_handler_thread;  // processes incoming messages
-+   VCOS_THREAD_T recycle_thread;       // processes recycled slots
-+   VCOS_THREAD_T lp_thread;            // processes low priority messages (eg suspend)
-+
-+   /* Local implementation of the trigger remote event */
-+   VCOS_EVENT_T trigger_event;
-+
-+   /* Local implementation of the recycle remote event */
-+   VCOS_EVENT_T recycle_event;
-+
-+   VCOS_EVENT_T lp_evt;
-+
-+   char *tx_data;
-+   char *rx_data;
-+   VCHIQ_SLOT_INFO_T *rx_info;
-+
-+   VCOS_MUTEX_T slot_mutex;
-+
-+   VCOS_MUTEX_T recycle_mutex;
-+
-+   VCOS_MUTEX_T suspend_resume_mutex;
-+   VCOS_MUTEX_T use_count_mutex;
-+
-+   /* Global use count for videocore.
-+    * This is equal to the sum of the use counts for all services.  When this hits
-+    * zero the videocore suspend procedure will be initiated. */
-+   int videocore_use_count;
-+
-+   /* Flag to indicate whether videocore is currently suspended */
-+   int videocore_suspended;
-+
-+   /* Indicates the byte position within the stream from where the next message
-+      will be read. The least significant bits are an index into the slot.
-+      The next bits are the index of the slot in remote->slot_queue. */
-+   int rx_pos;
-+
-+   /* A cached copy of local->tx_pos. Only write to local->tx_pos, and read
-+      from remote->tx_pos. */
-+   int local_tx_pos;
-+
-+   /* The slot_queue index of the slot to become available next. */
-+   int slot_queue_available;
-+
-+   /* A flag to indicate if any poll has been requested */
-+   int poll_needed;
-+
-+   /* An array of bit sets indicating which services must be polled. */
-+   VCOS_ATOMIC_FLAGS_T poll_services[BITSET_SIZE(VCHIQ_MAX_SERVICES)];
-+
-+   /* The number of the first unused service */
-+   int unused_service;
-+
-+   /* Signalled when a free slot becomes available. */
-+   VCOS_EVENT_T slot_available_event;
-+
-+   VCOS_EVENT_T slot_remove_event;
-+
-+   struct state_stats_struct
-+   {
-+      int slot_stalls;
-+      int ctrl_tx_count;
-+      int ctrl_rx_count;
-+      int error_count;
-+   } stats;
-+
-+   VCHIQ_SERVICE_T *services[VCHIQ_MAX_SERVICES];
-+   VCHIQ_SERVICE_QUOTA_T service_quotas[VCHIQ_MAX_SERVICES];
-+   VCHIQ_SLOT_INFO_T slot_info[VCHIQ_MAX_SLOTS];
-+};
-+
-+extern VCHIQ_SLOT_ZERO_T *
-+vchiq_init_slots(void *mem_base, int mem_size);
-+
-+extern VCHIQ_STATUS_T
-+vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, int is_master);
-+
-+extern VCHIQ_STATUS_T
-+vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance);
-+
-+extern VCHIQ_SERVICE_T *
-+vchiq_add_service_internal(VCHIQ_STATE_T *state,
-+   const VCHIQ_SERVICE_PARAMS_T *params, int srvstate,
-+   VCHIQ_INSTANCE_T instance);
-+
-+extern VCHIQ_STATUS_T
-+vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id);
-+
-+extern VCHIQ_STATUS_T
-+vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd);
-+
-+extern void
-+vchiq_terminate_service_internal(VCHIQ_SERVICE_T *service);
-+
-+extern void
-+vchiq_free_service_internal(VCHIQ_SERVICE_T *service);
-+
-+extern VCHIQ_STATUS_T
-+vchiq_shutdown_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance);
-+
-+extern VCHIQ_STATUS_T
-+vchiq_pause_internal(VCHIQ_STATE_T *state);
-+
-+extern VCHIQ_STATUS_T
-+vchiq_resume_internal(VCHIQ_STATE_T *state);
-+
-+extern void
-+remote_event_pollall(VCHIQ_STATE_T *state);
-+
-+extern VCHIQ_STATUS_T
-+vchiq_bulk_transfer(VCHIQ_SERVICE_T *service,
-+   VCHI_MEM_HANDLE_T memhandle, void *offset, int size, void *userdata,
-+   VCHIQ_BULK_MODE_T mode, VCHIQ_BULK_DIR_T dir);
-+
-+extern void
-+vchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state);
-+
-+extern void
-+vchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service);
-+
-+/* The following functions are called from vchiq_core, and external
-+   implementations must be provided. */
-+
-+extern VCHIQ_STATUS_T
-+vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk,
-+   VCHI_MEM_HANDLE_T memhandle, void *offset, int size, int dir);
-+
-+extern void
-+vchiq_transfer_bulk(VCHIQ_BULK_T *bulk);
-+
-+extern void
-+vchiq_complete_bulk(VCHIQ_BULK_T *bulk);
-+
-+extern VCHIQ_STATUS_T
-+vchiq_copy_from_user(void *dst, const void *src, int size);
-+
-+extern void
-+remote_event_signal(REMOTE_EVENT_T *event);
-+
-+extern void
-+vchiq_platform_paused(VCHIQ_STATE_T *state);
-+
-+extern void
-+vchiq_platform_resumed(VCHIQ_STATE_T *state);
-+
-+extern void
-+vchiq_dump(void *dump_context, const char *str, int len);
-+
-+extern void
-+vchiq_dump_platform_state(void *dump_context);
-+
-+extern void
-+vchiq_dump_platform_instances(void *dump_context);
-+
-+extern void
-+vchiq_dump_platform_service_state(void *dump_context,
-+   VCHIQ_SERVICE_T *service);
-+
-+#endif
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h
-@@ -0,0 +1,148 @@
-+/*
-+ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#ifndef VCHIQ_IF_H
-+#define VCHIQ_IF_H
-+
-+#include "interface/vchi/vchi_mh.h"
-+
-+#define VCHIQ_SLOT_SIZE          4096
-+#define VCHIQ_MAX_MSG_SIZE       (VCHIQ_SLOT_SIZE - sizeof(VCHIQ_HEADER_T))
-+#define VCHIQ_CHANNEL_SIZE       VCHIQ_MAX_MSG_SIZE /* For backwards compatibility */
-+
-+#define VCHIQ_MAKE_FOURCC(x0, x1, x2, x3)     (((x0) << 24) | ((x1) << 16) | ((x2) << 8) | (x3))
-+#define VCHIQ_GET_SERVICE_USERDATA(service)   (service->userdata)
-+#define VCHIQ_GET_SERVICE_FOURCC(service)     (service->fourcc)
-+
-+typedef enum {
-+   VCHIQ_SERVICE_OPENED,         // service, -, -
-+   VCHIQ_SERVICE_CLOSED,         // service, -, -
-+   VCHIQ_MESSAGE_AVAILABLE,      // service, header, -
-+   VCHIQ_BULK_TRANSMIT_DONE,     // service, -, bulk_userdata
-+   VCHIQ_BULK_RECEIVE_DONE,      // service, -, bulk_userdata
-+   VCHIQ_BULK_TRANSMIT_ABORTED,  // service, -, bulk_userdata
-+   VCHIQ_BULK_RECEIVE_ABORTED    // service, -, bulk_userdata
-+} VCHIQ_REASON_T;
-+
-+typedef enum
-+{
-+   VCHIQ_ERROR   = -1,
-+   VCHIQ_SUCCESS = 0,
-+   VCHIQ_RETRY   = 1
-+} VCHIQ_STATUS_T;
-+
-+typedef enum
-+{
-+   VCHIQ_BULK_MODE_CALLBACK,
-+   VCHIQ_BULK_MODE_BLOCKING,
-+   VCHIQ_BULK_MODE_NOCALLBACK
-+} VCHIQ_BULK_MODE_T;
-+
-+typedef enum
-+{
-+   VCHIQ_SERVICE_OPTION_AUTOCLOSE
-+} VCHIQ_SERVICE_OPTION_T;
-+
-+#ifdef __HIGHC__
-+/* Allow zero-sized arrays without warnings */
-+#pragma warning (push)
-+#pragma warning (disable : 4200)
-+#endif
-+
-+typedef struct vchiq_header_struct {
-+   /* The message identifier - opaque to applications. */
-+   int msgid;
-+
-+   /* Size of message data. */
-+   unsigned int size;      
-+
-+   char data[0];           /* message */
-+} VCHIQ_HEADER_T;
-+
-+#ifdef __HIGHC__
-+#pragma warning (pop)
-+#endif
-+
-+typedef struct {
-+   const void *data;
-+   int size;
-+} VCHIQ_ELEMENT_T;
-+
-+typedef const struct vchiq_service_base_struct *VCHIQ_SERVICE_HANDLE_T;
-+
-+typedef VCHIQ_STATUS_T (*VCHIQ_CALLBACK_T)(VCHIQ_REASON_T, VCHIQ_HEADER_T *, VCHIQ_SERVICE_HANDLE_T, void *);
-+
-+typedef struct vchiq_service_base_struct {
-+   int fourcc;
-+   VCHIQ_CALLBACK_T callback;
-+   void *userdata;
-+} VCHIQ_SERVICE_BASE_T;
-+
-+typedef struct vchiq_service_params_struct {
-+  int fourcc;
-+  VCHIQ_CALLBACK_T callback;
-+  void *userdata;
-+  short version;       /* Increment for non-trivial changes */
-+  short version_min;   /* Update for incompatible changes */
-+} VCHIQ_SERVICE_PARAMS_T;
-+
-+typedef struct vchiq_config_struct {
-+   int max_msg_size;
-+   int bulk_threshold; /* The message size aboce which it is better to use
-+                          a bulk transfer (<= max_msg_size) */
-+   int max_outstanding_bulks;
-+   int max_services;
-+   short version;      /* The version of VCHIQ */
-+   short version_min;  /* The minimum compatible version of VCHIQ */
-+} VCHIQ_CONFIG_T;
-+
-+typedef struct vchiq_instance_struct *VCHIQ_INSTANCE_T;
-+
-+extern VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *pinstance);
-+extern VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance);
-+extern VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance);
-+extern VCHIQ_STATUS_T vchiq_add_service(VCHIQ_INSTANCE_T instance, int fourcc, VCHIQ_CALLBACK_T callback, void *userdata, VCHIQ_SERVICE_HANDLE_T *pservice);
-+extern VCHIQ_STATUS_T vchiq_open_service(VCHIQ_INSTANCE_T instance, int fourcc, VCHIQ_CALLBACK_T callback, void *userdata, VCHIQ_SERVICE_HANDLE_T *pservice);
-+extern VCHIQ_STATUS_T vchiq_add_service_params(VCHIQ_INSTANCE_T instance,
-+   const VCHIQ_SERVICE_PARAMS_T *params,
-+   VCHIQ_SERVICE_HANDLE_T *pservice);
-+extern VCHIQ_STATUS_T vchiq_open_service_params(VCHIQ_INSTANCE_T instance,
-+   const VCHIQ_SERVICE_PARAMS_T *params,
-+   VCHIQ_SERVICE_HANDLE_T *pservice);
-+extern VCHIQ_STATUS_T vchiq_close_service(VCHIQ_SERVICE_HANDLE_T service);
-+extern VCHIQ_STATUS_T vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T service);
-+extern VCHIQ_STATUS_T vchiq_use_service(VCHIQ_SERVICE_HANDLE_T service);
-+extern VCHIQ_STATUS_T vchiq_release_service(VCHIQ_SERVICE_HANDLE_T service);
-+
-+extern VCHIQ_STATUS_T vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T service, const VCHIQ_ELEMENT_T *elements, int count);
-+extern void           vchiq_release_message(VCHIQ_SERVICE_HANDLE_T service, VCHIQ_HEADER_T *header);
-+extern VCHIQ_STATUS_T vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T service, const void *data, int size, void *userdata);
-+extern VCHIQ_STATUS_T vchiq_queue_bulk_receive(VCHIQ_SERVICE_HANDLE_T service, void *data, int size, void *userdata);
-+extern VCHIQ_STATUS_T vchiq_queue_bulk_transmit_handle(VCHIQ_SERVICE_HANDLE_T service, VCHI_MEM_HANDLE_T handle, const void *offset, int size, void *userdata);
-+extern VCHIQ_STATUS_T vchiq_queue_bulk_receive_handle(VCHIQ_SERVICE_HANDLE_T service, VCHI_MEM_HANDLE_T handle, void *offset, int size, void *userdata);
-+extern VCHIQ_STATUS_T vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T service, const void *data, int size, void *userdata, VCHIQ_BULK_MODE_T mode);
-+extern VCHIQ_STATUS_T vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T service, void *data, int size, void *userdata, VCHIQ_BULK_MODE_T mode);
-+extern VCHIQ_STATUS_T vchiq_bulk_transmit_handle(VCHIQ_SERVICE_HANDLE_T service, VCHI_MEM_HANDLE_T handle, const void *offset, int size, void *userdata, VCHIQ_BULK_MODE_T mode);
-+extern VCHIQ_STATUS_T vchiq_bulk_receive_handle(VCHIQ_SERVICE_HANDLE_T service, VCHI_MEM_HANDLE_T handle, void *offset, int size, void *userdata, VCHIQ_BULK_MODE_T mode);
-+extern int            vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T service);
-+extern VCHIQ_STATUS_T vchiq_get_config(VCHIQ_INSTANCE_T instance, int config_size, VCHIQ_CONFIG_T *pconfig);
-+extern VCHIQ_STATUS_T vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T service, VCHIQ_SERVICE_OPTION_T option, int value);
-+
-+extern VCHIQ_STATUS_T vchiq_dump_phys_mem( VCHIQ_SERVICE_HANDLE_T service, void *ptr, size_t num_bytes );
-+
-+#endif /* VCHIQ_IF_H */
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h
-@@ -0,0 +1,105 @@
-+/*
-+ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#ifndef VCHIQ_IOCTLS_H
-+#define VCHIQ_IOCTLS_H
-+
-+#include <linux/ioctl.h>
-+#include "vchiq_if.h"
-+
-+#define VCHIQ_IOC_MAGIC 0xc4
-+#define VCHIQ_INVALID_HANDLE -1
-+
-+typedef struct {
-+   VCHIQ_SERVICE_PARAMS_T params;
-+   int is_open;
-+   int is_vchi;
-+   int handle;       /* OUT */
-+} VCHIQ_CREATE_SERVICE_T;
-+
-+typedef struct {
-+   int handle;
-+   int count;
-+   const VCHIQ_ELEMENT_T *elements;
-+} VCHIQ_QUEUE_MESSAGE_T;
-+
-+typedef struct {
-+   int handle;
-+   void *data;
-+   int size;
-+   void *userdata;
-+   VCHIQ_BULK_MODE_T mode;
-+} VCHIQ_QUEUE_BULK_TRANSFER_T;
-+
-+typedef struct {
-+   VCHIQ_REASON_T reason;
-+   VCHIQ_HEADER_T *header;
-+   void *service_userdata;
-+   void *bulk_userdata;
-+} VCHIQ_COMPLETION_DATA_T;
-+
-+typedef struct {
-+   int count;
-+   VCHIQ_COMPLETION_DATA_T *buf;
-+   int msgbufsize;
-+   int msgbufcount; /* IN/OUT */
-+   void **msgbufs;
-+} VCHIQ_AWAIT_COMPLETION_T;
-+
-+typedef struct {
-+   int handle;
-+   int blocking;
-+   int bufsize;
-+   void *buf;
-+} VCHIQ_DEQUEUE_MESSAGE_T;
-+
-+typedef struct {
-+   int config_size;
-+   VCHIQ_CONFIG_T *pconfig;
-+} VCHIQ_GET_CONFIG_T;
-+
-+typedef struct {
-+   int handle;
-+   VCHIQ_SERVICE_OPTION_T option;
-+   int value;
-+} VCHIQ_SET_SERVICE_OPTION_T;
-+
-+typedef struct {
-+   void     *virt_addr;
-+   size_t    num_bytes;
-+} VCHIQ_DUMP_MEM_T;
-+
-+#define VCHIQ_IOC_CONNECT              _IO(VCHIQ_IOC_MAGIC,   0)
-+#define VCHIQ_IOC_SHUTDOWN             _IO(VCHIQ_IOC_MAGIC,   1)
-+#define VCHIQ_IOC_CREATE_SERVICE       _IOWR(VCHIQ_IOC_MAGIC, 2, VCHIQ_CREATE_SERVICE_T)
-+#define VCHIQ_IOC_REMOVE_SERVICE       _IO(VCHIQ_IOC_MAGIC,   3)
-+#define VCHIQ_IOC_QUEUE_MESSAGE        _IOW(VCHIQ_IOC_MAGIC,  4, VCHIQ_QUEUE_MESSAGE_T)
-+#define VCHIQ_IOC_QUEUE_BULK_TRANSMIT  _IOW(VCHIQ_IOC_MAGIC,  5, VCHIQ_QUEUE_BULK_TRANSFER_T)
-+#define VCHIQ_IOC_QUEUE_BULK_RECEIVE   _IOW(VCHIQ_IOC_MAGIC,  6, VCHIQ_QUEUE_BULK_TRANSFER_T)
-+#define VCHIQ_IOC_AWAIT_COMPLETION     _IOW(VCHIQ_IOC_MAGIC,  7, VCHIQ_AWAIT_COMPLETION_T)
-+#define VCHIQ_IOC_DEQUEUE_MESSAGE      _IOW(VCHIQ_IOC_MAGIC,  8, VCHIQ_DEQUEUE_MESSAGE_T)
-+#define VCHIQ_IOC_GET_CLIENT_ID        _IO(VCHIQ_IOC_MAGIC,   9)
-+#define VCHIQ_IOC_GET_CONFIG           _IOW(VCHIQ_IOC_MAGIC, 10, VCHIQ_GET_CONFIG_T)
-+#define VCHIQ_IOC_CLOSE_SERVICE        _IO(VCHIQ_IOC_MAGIC,  11)
-+#define VCHIQ_IOC_USE_SERVICE          _IO(VCHIQ_IOC_MAGIC,  12)
-+#define VCHIQ_IOC_RELEASE_SERVICE      _IO(VCHIQ_IOC_MAGIC,  13)
-+#define VCHIQ_IOC_SET_SERVICE_OPTION   _IOW(VCHIQ_IOC_MAGIC, 14, VCHIQ_SET_SERVICE_OPTION_T)
-+#define VCHIQ_IOC_DUMP_PHYS_MEM        _IOW(VCHIQ_IOC_MAGIC, 15, VCHIQ_DUMP_MEM_T)
-+#define VCHIQ_IOC_MAX                  15
-+
-+#endif
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c
-@@ -0,0 +1,297 @@
-+/*****************************************************************************
-+* Copyright 2001 - 2011 Broadcom Corporation.  All rights reserved.
-+*
-+* Unless you and Broadcom execute a separate written software license
-+* agreement governing use of this software, this software is licensed to you
-+* under the terms of the GNU General Public License version 2, available at
-+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-+*
-+* Notwithstanding the above, under no circumstances may you combine this
-+* software in any way with any other Broadcom software provided under a
-+* license other than the GPL, without Broadcom's express prior written
-+* consent.
-+*****************************************************************************/
-+
-+/* ---- Include Files ---------------------------------------------------- */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+
-+#include "vchiq_core.h"
-+#include "vchiq_arm.h"
-+#include "interface/vcos/vcos_logging.h"
-+
-+/* ---- Public Variables ------------------------------------------------- */
-+
-+extern VCOS_LOG_CAT_T vchiq_core_log_category;
-+#define  VCOS_LOG_CATEGORY (&vchiq_core_log_category)
-+
-+/* ---- Private Constants and Types -------------------------------------- */
-+
-+struct vchiq_instance_struct {
-+   VCHIQ_STATE_T *state;
-+
-+   int connected;
-+};
-+
-+/****************************************************************************
-+*
-+*   vchiq_initialise
-+*
-+***************************************************************************/
-+
-+VCHIQ_STATUS_T vchiq_initialise( VCHIQ_INSTANCE_T *instanceOut )
-+{
-+   VCHIQ_STATUS_T status = VCHIQ_ERROR;
-+   VCHIQ_STATE_T *state;
-+   VCHIQ_INSTANCE_T instance = NULL;
-+
-+   vcos_log_trace( "%s called", __func__ );
-+
-+   state = vchiq_get_state();
-+   if (!state)
-+   {
-+      printk( KERN_ERR "%s: videocore not initialized\n", __func__ );
-+      goto failed;
-+   }
-+
-+   instance = kzalloc( sizeof(*instance), GFP_KERNEL );
-+   if( !instance )
-+   {
-+      printk( KERN_ERR "%s: error allocating vchiq instance\n", __func__ );
-+      goto failed;
-+   }
-+
-+   instance->connected = 0;
-+   instance->state = state;
-+
-+   *instanceOut = instance;
-+   
-+   status = VCHIQ_SUCCESS;
-+
-+failed:
-+   vcos_log_trace( "%s(%p): returning %d", __func__, instance, status );
-+
-+   return status;
-+}
-+
-+/****************************************************************************
-+*
-+*   vchiq_shutdown
-+*
-+***************************************************************************/
-+
-+VCHIQ_STATUS_T vchiq_shutdown( VCHIQ_INSTANCE_T instance )
-+{
-+   VCHIQ_STATUS_T status;
-+   VCHIQ_STATE_T *state = instance->state;
-+
-+   vcos_log_trace( "%s(%p) called", __func__, instance );
-+
-+   vcos_mutex_lock(&state->mutex);
-+
-+   /* Remove all services */
-+   status = vchiq_shutdown_internal(state, instance);
-+
-+   vcos_mutex_unlock(&state->mutex);
-+
-+   if (status == VCHIQ_SUCCESS)
-+      kfree(instance);
-+
-+   vcos_log_trace( "%s(%p): returning %d", __func__, instance, status );
-+
-+   return status;
-+}
-+
-+/****************************************************************************
-+*
-+*   vchiq_is_connected
-+*
-+***************************************************************************/
-+
-+int vchiq_is_connected(VCHIQ_INSTANCE_T instance)
-+{
-+   return instance->connected;
-+}
-+
-+/****************************************************************************
-+*
-+*   vchiq_connect
-+*
-+***************************************************************************/
-+
-+VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance)
-+{
-+   VCHIQ_STATUS_T status;
-+   VCHIQ_STATE_T *state = instance->state;
-+
-+   vcos_log_trace( "%s(%p) called", __func__, instance );
-+
-+   if (vcos_mutex_lock(&state->mutex) != VCOS_SUCCESS) {
-+      vcos_log_trace( "%s: call to vcos_mutex_lock failed", __func__ );
-+      status = VCHIQ_RETRY;
-+      goto failed;
-+   }
-+   status = vchiq_connect_internal(state, instance);
-+
-+   if (status == VCHIQ_SUCCESS)
-+      instance->connected = 1;
-+
-+   vcos_mutex_unlock(&state->mutex);
-+
-+failed:
-+   vcos_log_trace( "%s(%p): returning %d", __func__, instance, status );
-+
-+   return status;
-+}
-+
-+/****************************************************************************
-+*
-+*   vchiq_add_service
-+*
-+***************************************************************************/
-+
-+VCHIQ_STATUS_T vchiq_add_service(
-+   VCHIQ_INSTANCE_T        instance,
-+   int                     fourcc,
-+   VCHIQ_CALLBACK_T        callback,
-+   void                   *userdata,
-+   VCHIQ_SERVICE_HANDLE_T *pservice)
-+{
-+   VCHIQ_SERVICE_PARAMS_T params;
-+
-+   params.fourcc        = fourcc;
-+   params.callback      = callback;
-+   params.userdata      = userdata;
-+   params.version       = 0;
-+   params.version_min   = 0;
-+
-+   return vchiq_add_service_params(instance, &params, pservice);
-+}
-+
-+/****************************************************************************
-+*
-+*   vchiq_open_service
-+*
-+***************************************************************************/
-+
-+VCHIQ_STATUS_T vchiq_open_service(
-+   VCHIQ_INSTANCE_T        instance,
-+   int                     fourcc,
-+   VCHIQ_CALLBACK_T        callback,
-+   void                   *userdata,
-+   VCHIQ_SERVICE_HANDLE_T *pservice)
-+{
-+   VCHIQ_SERVICE_PARAMS_T params;
-+
-+   params.fourcc        = fourcc;
-+   params.callback      = callback;
-+   params.userdata      = userdata;
-+   params.version       = 0;
-+   params.version_min   = 0;
-+
-+   return vchiq_open_service_params(instance, &params, pservice);
-+}
-+
-+/****************************************************************************
-+*
-+*   vchiq_add_service_params
-+*
-+***************************************************************************/
-+
-+VCHIQ_STATUS_T vchiq_add_service_params(
-+   VCHIQ_INSTANCE_T              instance,
-+   const VCHIQ_SERVICE_PARAMS_T *params,
-+   VCHIQ_SERVICE_HANDLE_T       *pservice)
-+{
-+   VCHIQ_STATUS_T status;
-+   VCHIQ_STATE_T *state = instance->state;
-+   VCHIQ_SERVICE_T *service;
-+   int srvstate;
-+
-+   vcos_log_trace( "%s(%p) called", __func__, instance );
-+
-+   *pservice = NULL;
-+
-+   srvstate = vchiq_is_connected( instance )
-+      ? VCHIQ_SRVSTATE_LISTENING
-+      : VCHIQ_SRVSTATE_HIDDEN;
-+
-+   vcos_mutex_lock(&state->mutex);
-+
-+   service = vchiq_add_service_internal(
-+      state,
-+      params,
-+      srvstate,
-+      instance);
-+
-+   vcos_mutex_unlock(&state->mutex);
-+
-+   if ( service  )
-+   {
-+      *pservice = &service->base;
-+      status = VCHIQ_SUCCESS;
-+   }
-+   else
-+   {
-+      status = VCHIQ_ERROR;
-+   }
-+
-+   vcos_log_trace( "%s(%p): returning %d", __func__, instance, status );
-+
-+   return status;
-+}
-+
-+/****************************************************************************
-+*
-+*   vchiq_open_service_params
-+*
-+***************************************************************************/
-+
-+VCHIQ_STATUS_T vchiq_open_service_params(
-+   VCHIQ_INSTANCE_T              instance,
-+   const VCHIQ_SERVICE_PARAMS_T *params,
-+   VCHIQ_SERVICE_HANDLE_T       *pservice)
-+{
-+   VCHIQ_STATUS_T   status = VCHIQ_ERROR;
-+   VCHIQ_STATE_T   *state = instance->state;
-+   VCHIQ_SERVICE_T *service;
-+
-+   vcos_log_trace( "%s(%p) called", __func__, instance );
-+
-+   *pservice = NULL;
-+
-+   if (!vchiq_is_connected(instance))
-+      goto failed;
-+
-+   vcos_mutex_lock(&state->mutex);
-+
-+   service = vchiq_add_service_internal(state,
-+      params,
-+      VCHIQ_SRVSTATE_OPENING,
-+      instance);
-+
-+   vcos_mutex_unlock(&state->mutex);
-+
-+   if ( service  )
-+   {
-+      status = vchiq_open_service_internal(service, current->pid);
-+      if ( status == VCHIQ_SUCCESS )
-+         *pservice = &service->base;
-+      else
-+         vchiq_remove_service(&service->base);
-+   }
-+
-+failed:
-+   vcos_log_trace( "%s(%p): returning %d", __func__, instance, status );
-+
-+   return status;
-+}
-+
-+EXPORT_SYMBOL(vchiq_initialise);
-+EXPORT_SYMBOL(vchiq_shutdown);
-+EXPORT_SYMBOL(vchiq_connect);
-+EXPORT_SYMBOL(vchiq_add_service);
-+EXPORT_SYMBOL(vchiq_open_service);
-+EXPORT_SYMBOL(vchiq_add_service_params);
-+EXPORT_SYMBOL(vchiq_open_service_params);
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_lib.c
-@@ -0,0 +1,1518 @@
-+/*
-+ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#include <unistd.h>
-+#include <fcntl.h>
-+#include <sys/ioctl.h>
-+#include <stdio.h>
-+
-+#include "vchiq.h"
-+#include "vchiq_cfg.h"
-+#include "vchiq_ioctl.h"
-+#include "interface/vchi/vchi.h"
-+#include "interface/vchi/common/endian.h"
-+#include "interface/vcos/vcos.h"
-+
-+#define VCHIQ_MAX_INSTANCE_SERVICES 32
-+#define MSGBUF_SIZE (VCHIQ_MAX_MSG_SIZE + sizeof(VCHIQ_HEADER_T))
-+
-+#define RETRY(r,x) do { r = x; } while ((r == -1) && (errno == EINTR))
-+
-+#define VCOS_LOG_CATEGORY (&vchiq_lib_log_category)
-+
-+typedef struct vchiq_service_struct
-+{
-+   VCHIQ_SERVICE_BASE_T base;
-+   int handle;
-+   int fd;
-+   VCHI_CALLBACK_T vchi_callback;
-+   void *peek_buf;
-+   int peek_size;
-+   int client_id;
-+} VCHIQ_SERVICE_T;
-+
-+typedef struct vchiq_service_struct VCHI_SERVICE_T;
-+
-+struct vchiq_instance_struct
-+{
-+   int fd;
-+   int initialised;
-+   int connected;
-+   VCOS_THREAD_T completion_thread;
-+   VCOS_MUTEX_T mutex;
-+   int used_services;
-+   VCHIQ_SERVICE_T services[VCHIQ_MAX_INSTANCE_SERVICES];
-+} vchiq_instance;
-+
-+typedef struct vchiq_instance_struct VCHI_STATE_T;
-+
-+/* Local data */
-+static VCOS_LOG_LEVEL_T vchiq_default_lib_log_level = VCOS_LOG_WARN;
-+static VCOS_LOG_CAT_T vchiq_lib_log_category;
-+static VCOS_MUTEX_T vchiq_lib_mutex;
-+static void *free_msgbufs;
-+
-+
-+/* Local utility functions */
-+static VCHIQ_INSTANCE_T
-+vchiq_lib_init(void);
-+
-+static void *completion_thread(void *);
-+
-+static VCHIQ_STATUS_T
-+create_service(VCHIQ_INSTANCE_T instance,
-+   const VCHIQ_SERVICE_PARAMS_T *params,
-+   VCHI_CALLBACK_T vchi_callback,
-+   int is_open,
-+   VCHIQ_SERVICE_HANDLE_T *pservice);
-+
-+static int
-+fill_peek_buf(VCHI_SERVICE_T *service,
-+   VCHI_FLAGS_T flags);
-+
-+static void *
-+alloc_msgbuf(void);
-+
-+static void
-+free_msgbuf(void *buf);
-+
-+static __inline int
-+is_valid_instance(VCHIQ_INSTANCE_T instance)
-+{
-+   return (instance == &vchiq_instance) && (instance->initialised > 0);
-+}
-+
-+/*
-+ * VCHIQ API
-+ */
-+
-+VCHIQ_STATUS_T
-+vchiq_initialise(VCHIQ_INSTANCE_T *pinstance)
-+{
-+   VCHIQ_INSTANCE_T instance;
-+
-+   instance = vchiq_lib_init();
-+
-+   vcos_log_trace( "%s: returning instance handle %p", __func__, instance );
-+
-+   *pinstance = instance;
-+
-+   return (instance != NULL) ? VCHIQ_SUCCESS : VCHIQ_ERROR;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_shutdown(VCHIQ_INSTANCE_T instance)
-+{
-+   vcos_log_trace( "%s called", __func__ );
-+
-+   if (!is_valid_instance(instance))
-+      return VCHIQ_ERROR;
-+
-+   vcos_mutex_lock(&instance->mutex);
-+
-+   if (instance->initialised == 1)
-+   {
-+      int i;
-+
-+      instance->initialised = -1; /* Enter limbo */
-+
-+      /* Remove all services */
-+
-+      for (i = 0; i < instance->used_services; i++)
-+      {
-+         if (instance->services[i].handle != VCHIQ_INVALID_HANDLE)
-+         {
-+            vchiq_remove_service(&instance->services[i].base);
-+            instance->services[i].handle = VCHIQ_INVALID_HANDLE;
-+         }
-+      }
-+
-+      if (instance->connected)
-+      {
-+         int ret;
-+         RETRY(ret, ioctl(instance->fd, VCHIQ_IOC_SHUTDOWN, 0));
-+         vcos_assert(ret == 0);
-+         vcos_thread_join(&instance->completion_thread, NULL);
-+         instance->connected = 0;
-+      }
-+
-+      close(instance->fd);
-+      instance->fd = -1;
-+   }
-+   else if (instance->initialised > 1)
-+   {
-+      instance->initialised--;
-+   }
-+
-+   vcos_mutex_unlock(&instance->mutex);
-+
-+   vcos_global_lock();
-+
-+   if (instance->initialised == -1)
-+   {
-+      vcos_mutex_delete(&instance->mutex);
-+      instance->initialised = 0;
-+   }
-+
-+   vcos_global_unlock();
-+
-+   vcos_log_trace( "%s returning", __func__ );
-+
-+   return VCHIQ_SUCCESS;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_connect(VCHIQ_INSTANCE_T instance)
-+{
-+   VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
-+
-+   vcos_log_trace( "%s called", __func__ );
-+
-+   if (!is_valid_instance(instance))
-+      return VCHIQ_ERROR;
-+
-+   vcos_mutex_lock(&instance->mutex);
-+
-+   if (!instance->connected)
-+   {
-+      int ret = ioctl(instance->fd, VCHIQ_IOC_CONNECT, 0);
-+      if (ret == 0)
-+      {
-+         VCOS_THREAD_ATTR_T attrs;
-+         instance->connected = 1;
-+         vcos_thread_attr_init(&attrs);
-+         vcos_thread_create(&instance->completion_thread, "VCHIQ completion",
-+                            &attrs, completion_thread, instance);
-+      }
-+      else
-+      {
-+         status = VCHIQ_ERROR;
-+      }
-+   }
-+
-+   vcos_mutex_unlock(&instance->mutex);
-+
-+   return status;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_add_service(VCHIQ_INSTANCE_T instance,
-+   int fourcc,
-+   VCHIQ_CALLBACK_T callback,
-+   void *userdata,
-+   VCHIQ_SERVICE_HANDLE_T *pservice)
-+{
-+   VCHIQ_SERVICE_PARAMS_T params;
-+
-+   params.fourcc        = fourcc;
-+   params.callback      = callback;
-+   params.userdata      = userdata;
-+   params.version       = 0;
-+   params.version_min   = 0;
-+
-+   return vchiq_add_service_params(instance, &params, pservice);
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_open_service(VCHIQ_INSTANCE_T instance,
-+   int fourcc,
-+   VCHIQ_CALLBACK_T callback,
-+   void *userdata,
-+   VCHIQ_SERVICE_HANDLE_T *pservice)
-+{
-+   VCHIQ_SERVICE_PARAMS_T params;
-+
-+   params.fourcc        = fourcc;
-+   params.callback      = callback;
-+   params.userdata      = userdata;
-+   params.version       = 0;
-+   params.version_min   = 0;
-+
-+   return vchiq_open_service_params(instance, &params, pservice);
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_add_service_params(VCHIQ_INSTANCE_T instance,
-+   const VCHIQ_SERVICE_PARAMS_T *params,
-+   VCHIQ_SERVICE_HANDLE_T *pservice)
-+{
-+   VCHIQ_STATUS_T status;
-+
-+   vcos_log_trace( "%s called fourcc = 0x%08x (%c%c%c%c)",
-+                   __func__,
-+                   params->fourcc,
-+                   (params->fourcc >> 24) & 0xff,
-+                   (params->fourcc >> 16) & 0xff,
-+                   (params->fourcc >>  8) & 0xff,
-+                   (params->fourcc      ) & 0xff );
-+
-+   if (!params->callback)
-+      return VCHIQ_ERROR;
-+
-+   if (!is_valid_instance(instance))
-+      return VCHIQ_ERROR;
-+
-+   status = create_service(instance,
-+      params,
-+      NULL/*vchi_callback*/,
-+      0/*!open*/,
-+      pservice);
-+
-+   vcos_log_trace( "%s returning service handle = 0x%08x", __func__, (uint32_t)*pservice );
-+
-+   return status;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_open_service_params(VCHIQ_INSTANCE_T instance,
-+   const VCHIQ_SERVICE_PARAMS_T *params,
-+   VCHIQ_SERVICE_HANDLE_T *pservice)
-+{
-+   VCHIQ_STATUS_T status;
-+
-+   vcos_log_trace( "%s called fourcc = 0x%08x (%c%c%c%c)",
-+                   __func__,
-+                   params->fourcc,
-+                   (params->fourcc >> 24) & 0xff,
-+                   (params->fourcc >> 16) & 0xff,
-+                   (params->fourcc >>  8) & 0xff,
-+                   (params->fourcc      ) & 0xff );
-+
-+   if (!params->callback)
-+      return VCHIQ_ERROR;
-+
-+   if (!is_valid_instance(instance))
-+      return VCHIQ_ERROR;
-+
-+   status = create_service(instance,
-+      params,
-+      NULL/*vchi_callback*/,
-+      1/*open*/,
-+      pservice);
-+
-+   vcos_log_trace( "%s returning service handle = 0x%08x", __func__, (uint32_t)*pservice );
-+
-+   return status;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_close_service(VCHIQ_SERVICE_HANDLE_T handle)
-+{
-+   VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
-+   int ret;
-+
-+   vcos_log_trace( "%s called service handle = 0x%08x", __func__, (uint32_t)handle );
-+
-+   RETRY(ret,ioctl(service->fd, VCHIQ_IOC_CLOSE_SERVICE, service->handle));
-+
-+   if (ret != 0)
-+      return VCHIQ_ERROR;
-+
-+   service->handle = VCHIQ_INVALID_HANDLE;
-+   return VCHIQ_SUCCESS;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T handle)
-+{
-+   VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
-+   int ret;
-+
-+   vcos_log_trace( "%s called service handle = 0x%08x", __func__, (uint32_t)handle );
-+
-+   RETRY(ret,ioctl(service->fd, VCHIQ_IOC_REMOVE_SERVICE, service->handle));
-+
-+   if (ret != 0)
-+      return VCHIQ_ERROR;
-+
-+   service->handle = VCHIQ_INVALID_HANDLE;
-+   return VCHIQ_SUCCESS;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T handle,
-+   const VCHIQ_ELEMENT_T *elements,
-+   int count)
-+{
-+   VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
-+   VCHIQ_QUEUE_MESSAGE_T args;
-+   int ret;
-+
-+   vcos_log_trace( "%s called service handle = 0x%08x", __func__, (uint32_t)handle );
-+
-+   args.handle = service->handle;
-+   args.elements = elements;
-+   args.count = count;
-+   RETRY(ret, ioctl(service->fd, VCHIQ_IOC_QUEUE_MESSAGE, &args));
-+
-+   return (ret >= 0) ? VCHIQ_SUCCESS : VCHIQ_ERROR;
-+}
-+
-+void
-+vchiq_release_message(VCHIQ_SERVICE_HANDLE_T handle,
-+   VCHIQ_HEADER_T *header)
-+{
-+   vcos_log_trace( "%s handle=%08x, header=%x", __func__, (uint32_t)handle, (uint32_t)header );
-+
-+   free_msgbuf(header);
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle,
-+   const void *data,
-+   int size,
-+   void *userdata)
-+{
-+   VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
-+   VCHIQ_QUEUE_BULK_TRANSFER_T args;
-+   int ret;
-+
-+   vcos_log_trace( "%s called service handle = 0x%08x", __func__, (uint32_t)handle );
-+
-+   args.handle = service->handle;
-+   args.data = (void *)data;
-+   args.size = size;
-+   args.userdata = userdata;
-+   args.mode = VCHIQ_BULK_MODE_CALLBACK;
-+   RETRY(ret, ioctl(service->fd, VCHIQ_IOC_QUEUE_BULK_TRANSMIT, &args));
-+
-+   return (ret >= 0) ? VCHIQ_SUCCESS : VCHIQ_ERROR;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_queue_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle,
-+   void *data,
-+   int size,
-+   void *userdata)
-+{
-+   VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
-+   VCHIQ_QUEUE_BULK_TRANSFER_T args;
-+   int ret;
-+
-+   vcos_log_trace( "%s called service handle = 0x%08x", __func__, (uint32_t)handle );
-+
-+   args.handle = service->handle;
-+   args.data = data;
-+   args.size = size;
-+   args.userdata = userdata;
-+   args.mode = VCHIQ_BULK_MODE_CALLBACK;
-+   RETRY(ret, ioctl(service->fd, VCHIQ_IOC_QUEUE_BULK_RECEIVE, &args));
-+
-+   return (ret >= 0) ? VCHIQ_SUCCESS : VCHIQ_ERROR;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_queue_bulk_transmit_handle(VCHIQ_SERVICE_HANDLE_T handle,
-+   VCHI_MEM_HANDLE_T memhandle,
-+   const void *offset,
-+   int size,
-+   void *userdata)
-+{
-+   vcos_assert(memhandle == VCHI_MEM_HANDLE_INVALID);
-+
-+   vcos_log_trace( "%s called service handle = 0x%08x", __func__, (uint32_t)handle );
-+
-+   return vchiq_queue_bulk_transmit(handle, offset, size, userdata);
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_queue_bulk_receive_handle(VCHIQ_SERVICE_HANDLE_T handle,
-+   VCHI_MEM_HANDLE_T memhandle,
-+   void *offset,
-+   int size,
-+   void *userdata)
-+{
-+   vcos_assert(memhandle == VCHI_MEM_HANDLE_INVALID);
-+
-+   vcos_log_trace( "%s called service handle = 0x%08x", __func__, (uint32_t)handle );
-+
-+   return vchiq_queue_bulk_receive(handle, offset, size, userdata);
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle,
-+   const void *data,
-+   int size,
-+   void *userdata,
-+   VCHIQ_BULK_MODE_T mode)
-+{
-+   VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
-+   VCHIQ_QUEUE_BULK_TRANSFER_T args;
-+   int ret;
-+
-+   vcos_log_trace( "%s called service handle = 0x%08x", __func__, (uint32_t)handle );
-+
-+   args.handle = service->handle;
-+   args.data = (void *)data;
-+   args.size = size;
-+   args.userdata = userdata;
-+   args.mode = mode;
-+   RETRY(ret, ioctl(service->fd, VCHIQ_IOC_QUEUE_BULK_TRANSMIT, &args));
-+
-+   return (ret >= 0) ? VCHIQ_SUCCESS : VCHIQ_ERROR;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle,
-+   void *data,
-+   int size,
-+   void *userdata,
-+   VCHIQ_BULK_MODE_T mode)
-+{
-+   VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
-+   VCHIQ_QUEUE_BULK_TRANSFER_T args;
-+   int ret;
-+
-+   vcos_log_trace( "%s called service handle = 0x%08x", __func__, (uint32_t)handle );
-+
-+   args.handle = service->handle;
-+   args.data = data;
-+   args.size = size;
-+   args.userdata = userdata;
-+   args.mode = mode;
-+   RETRY(ret, ioctl(service->fd, VCHIQ_IOC_QUEUE_BULK_RECEIVE, &args));
-+
-+   return (ret >= 0) ? VCHIQ_SUCCESS : VCHIQ_ERROR;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_bulk_transmit_handle(VCHIQ_SERVICE_HANDLE_T handle,
-+   VCHI_MEM_HANDLE_T memhandle,
-+   const void *offset,
-+   int size,
-+   void *userdata,
-+   VCHIQ_BULK_MODE_T mode)
-+{
-+   vcos_assert(memhandle == VCHI_MEM_HANDLE_INVALID);
-+
-+   return vchiq_bulk_transmit(handle, offset, size, userdata, mode);
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_bulk_receive_handle(VCHIQ_SERVICE_HANDLE_T handle,
-+   VCHI_MEM_HANDLE_T memhandle,
-+   void *offset,
-+   int size,
-+   void *userdata,
-+   VCHIQ_BULK_MODE_T mode)
-+{
-+   vcos_assert(memhandle == VCHI_MEM_HANDLE_INVALID);
-+
-+   return vchiq_bulk_receive(handle, offset, size, userdata, mode);
-+}
-+
-+int
-+vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T handle)
-+{
-+   VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
-+
-+   return ioctl(service->fd, VCHIQ_IOC_GET_CLIENT_ID, service->handle);
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_get_config(VCHIQ_INSTANCE_T instance,
-+   int config_size,
-+   VCHIQ_CONFIG_T *pconfig)
-+{
-+   VCHIQ_GET_CONFIG_T args;
-+   int ret;
-+
-+   if (!is_valid_instance(instance))
-+      return VCHIQ_ERROR;
-+
-+   args.config_size = config_size;
-+   args.pconfig = pconfig;
-+
-+   RETRY(ret, ioctl(instance->fd, VCHIQ_IOC_GET_CONFIG, &args));
-+
-+   return (ret >= 0) ? VCHIQ_SUCCESS : VCHIQ_ERROR;
-+}
-+
-+int32_t
-+vchiq_use_service( const VCHIQ_SERVICE_HANDLE_T handle )
-+{
-+    VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
-+    int ret;
-+    RETRY(ret,ioctl(service->fd, VCHIQ_IOC_USE_SERVICE, service->handle));
-+    return ret;
-+}
-+
-+int32_t
-+vchiq_release_service( const VCHIQ_SERVICE_HANDLE_T handle )
-+{
-+    VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
-+    int ret;
-+    RETRY(ret,ioctl(service->fd, VCHIQ_IOC_RELEASE_SERVICE, service->handle));
-+    return ret;
-+}
-+
-+VCHIQ_STATUS_T
-+vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T handle,
-+   VCHIQ_SERVICE_OPTION_T option, int value)
-+{
-+   VCHIQ_SET_SERVICE_OPTION_T args;
-+   VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
-+   int ret;
-+
-+   args.handle = service->handle;
-+   args.option = option;
-+   args.value  = value;
-+
-+   RETRY(ret, ioctl(service->fd, VCHIQ_IOC_SET_SERVICE_OPTION, &args));
-+
-+   return (ret >= 0) ? VCHIQ_SUCCESS : VCHIQ_ERROR;
-+}
-+
-+/*
-+ * VCHI API
-+ */
-+
-+/* ----------------------------------------------------------------------
-+ * return pointer to the mphi message driver function table
-+ * -------------------------------------------------------------------- */
-+const VCHI_MESSAGE_DRIVER_T *
-+vchi_mphi_message_driver_func_table( void )
-+{
-+   return NULL;
-+}
-+
-+/* ----------------------------------------------------------------------
-+ * return a pointer to the 'single' connection driver fops
-+ * -------------------------------------------------------------------- */
-+const VCHI_CONNECTION_API_T *
-+single_get_func_table( void )
-+{
-+   return NULL;
-+}
-+
-+VCHI_CONNECTION_T *
-+vchi_create_connection( const VCHI_CONNECTION_API_T * function_table,
-+   const VCHI_MESSAGE_DRIVER_T * low_level )
-+{
-+   vcos_unused(function_table);
-+   vcos_unused(low_level);
-+
-+   return NULL;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_msg_peek
-+ *
-+ * Arguments:  const VCHI_SERVICE_HANDLE_T handle,
-+ *             void **data,
-+ *             uint32_t *msg_size,
-+ *             VCHI_FLAGS_T flags
-+ *
-+ * Description: Routine to return a pointer to the current message (to allow in place processing)
-+ *              The message can be removed using vchi_msg_remove when you're finished
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+int32_t
-+vchi_msg_peek( VCHI_SERVICE_HANDLE_T handle,
-+   void **data,
-+   uint32_t *msg_size,
-+   VCHI_FLAGS_T flags )
-+{
-+   VCHI_SERVICE_T *service = (VCHI_SERVICE_T *)handle;
-+   int ret;
-+
-+   ret = fill_peek_buf(service, flags);
-+
-+   if (ret == 0)
-+   {
-+      *data = service->peek_buf;
-+      *msg_size = service->peek_size;
-+   }
-+
-+   return ret;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_msg_remove
-+ *
-+ * Arguments:  const VCHI_SERVICE_HANDLE_T handle,
-+ *
-+ * Description: Routine to remove a message (after it has been read with vchi_msg_peek)
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+int32_t
-+vchi_msg_remove( VCHI_SERVICE_HANDLE_T handle )
-+{
-+   VCHI_SERVICE_T *service = (VCHI_SERVICE_T *)handle;
-+
-+   /* Why would you call vchi_msg_remove without calling vchi_msg_peek first? */
-+   vcos_assert(service->peek_size >= 0);
-+
-+   /* Invalidate the content but reuse the buffer */
-+   service->peek_size = -1;
-+
-+   return 0;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_msg_queue
-+ *
-+ * Arguments:  VCHI_SERVICE_HANDLE_T handle,
-+ *             const void *data,
-+ *             uint32_t data_size,
-+ *             VCHI_FLAGS_T flags,
-+ *             void *msg_handle,
-+ *
-+ * Description: Thin wrapper to queue a message onto a connection
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+int32_t
-+vchi_msg_queue( VCHI_SERVICE_HANDLE_T handle,
-+   const void * data,
-+   uint32_t data_size,
-+   VCHI_FLAGS_T flags,
-+   void * msg_handle )
-+{
-+   VCHI_SERVICE_T *service = (VCHI_SERVICE_T *)handle;
-+   VCHIQ_QUEUE_MESSAGE_T args;
-+   VCHIQ_ELEMENT_T element = {data, data_size};
-+   int ret;
-+
-+   vcos_unused(msg_handle);
-+   vcos_assert(flags == VCHI_FLAGS_BLOCK_UNTIL_QUEUED);
-+
-+   args.handle = service->handle;
-+   args.elements = &element;
-+   args.count = 1;
-+   RETRY(ret, ioctl(service->fd, VCHIQ_IOC_QUEUE_MESSAGE, &args));
-+
-+   return ret;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_bulk_queue_receive
-+ *
-+ * Arguments:  VCHI_BULK_HANDLE_T handle,
-+ *             void *data_dst,
-+ *             const uint32_t data_size,
-+ *             VCHI_FLAGS_T flags
-+ *             void *bulk_handle
-+ *
-+ * Description: Routine to setup a rcv buffer
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+int32_t
-+vchi_bulk_queue_receive( VCHI_SERVICE_HANDLE_T handle,
-+   void * data_dst,
-+   uint32_t data_size,
-+   VCHI_FLAGS_T flags,
-+   void * bulk_handle )
-+{
-+   VCHI_SERVICE_T *service = (VCHI_SERVICE_T *)handle;
-+   VCHIQ_QUEUE_BULK_TRANSFER_T args;
-+   int ret;
-+
-+   switch ((int)flags) {
-+   case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE | VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
-+      args.mode = VCHIQ_BULK_MODE_CALLBACK;
-+      break;
-+   case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE:
-+      args.mode = VCHIQ_BULK_MODE_BLOCKING;
-+      break;
-+   case VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
-+   case VCHI_FLAGS_NONE:
-+      args.mode = VCHIQ_BULK_MODE_NOCALLBACK;
-+      break;
-+   default:
-+      vcos_assert(0);
-+      break;
-+   }
-+
-+   args.handle = service->handle;
-+   args.data = data_dst;
-+   args.size = data_size;
-+   args.userdata = bulk_handle;
-+   RETRY(ret, ioctl(service->fd, VCHIQ_IOC_QUEUE_BULK_RECEIVE, &args));
-+
-+   return ret;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_bulk_queue_transmit
-+ *
-+ * Arguments:  VCHI_BULK_HANDLE_T handle,
-+ *             const void *data_src,
-+ *             uint32_t data_size,
-+ *             VCHI_FLAGS_T flags,
-+ *             void *bulk_handle
-+ *
-+ * Description: Routine to transmit some data
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+int32_t
-+vchi_bulk_queue_transmit( VCHI_SERVICE_HANDLE_T handle,
-+   const void * data_src,
-+   uint32_t data_size,
-+   VCHI_FLAGS_T flags,
-+   void * bulk_handle )
-+{
-+   VCHI_SERVICE_T *service = (VCHI_SERVICE_T *)handle;
-+   VCHIQ_QUEUE_BULK_TRANSFER_T args;
-+   int ret;
-+
-+   switch ((int)flags) {
-+   case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE | VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
-+      args.mode = VCHIQ_BULK_MODE_CALLBACK;
-+      break;
-+   case VCHI_FLAGS_BLOCK_UNTIL_DATA_READ:
-+   case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE:
-+      args.mode = VCHIQ_BULK_MODE_BLOCKING;
-+      break;
-+   case VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
-+   case VCHI_FLAGS_NONE:
-+      args.mode = VCHIQ_BULK_MODE_NOCALLBACK;
-+      break;
-+   default:
-+      vcos_assert(0);
-+      break;
-+   }
-+
-+   args.handle = service->handle;
-+   args.data = (void *)data_src;
-+   args.size = data_size;
-+   args.userdata = bulk_handle;
-+   RETRY(ret, ioctl(service->fd, VCHIQ_IOC_QUEUE_BULK_TRANSMIT, &args));
-+
-+   return ret;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_msg_dequeue
-+ *
-+ * Arguments:  VCHI_SERVICE_HANDLE_T handle,
-+ *             void *data,
-+ *             uint32_t max_data_size_to_read,
-+ *             uint32_t *actual_msg_size
-+ *             VCHI_FLAGS_T flags
-+ *
-+ * Description: Routine to dequeue a message into the supplied buffer
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+int32_t
-+vchi_msg_dequeue( VCHI_SERVICE_HANDLE_T handle,
-+   void *data,
-+   uint32_t max_data_size_to_read,
-+   uint32_t *actual_msg_size,
-+   VCHI_FLAGS_T flags )
-+{
-+   VCHI_SERVICE_T *service = (VCHI_SERVICE_T *)handle;
-+   VCHIQ_DEQUEUE_MESSAGE_T args;
-+   int ret;
-+
-+   vcos_assert(flags == VCHI_FLAGS_NONE || flags == VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE);
-+
-+   if (service->peek_size >= 0)
-+   {
-+      fprintf(stderr, "vchi_msg_dequeue -> using peek buffer\n");
-+      if ((uint32_t)service->peek_size <= max_data_size_to_read)
-+      {
-+         memcpy(data, service->peek_buf, service->peek_size);
-+         *actual_msg_size = service->peek_size;
-+         /* Invalidate the peek data, but retain the buffer */
-+         service->peek_size = -1;
-+         ret = 0;
-+      }
-+      else
-+      {
-+         ret = -1;
-+      }
-+   }
-+   else
-+   {
-+      args.handle = service->handle;
-+      args.blocking = (flags == VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE);
-+      args.bufsize = max_data_size_to_read;
-+      args.buf = data;
-+      RETRY(ret, ioctl(service->fd, VCHIQ_IOC_DEQUEUE_MESSAGE, &args));
-+      if (ret >= 0)
-+      {
-+         *actual_msg_size = ret;
-+         ret = 0;
-+      }
-+   }
-+
-+   if ((ret < 0) && (errno != EWOULDBLOCK))
-+      fprintf(stderr, "vchi_msg_dequeue -> %d(%d)\n", ret, errno);
-+
-+   return ret;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_msg_queuev
-+ *
-+ * Arguments:  VCHI_SERVICE_HANDLE_T handle,
-+ *             const void *data,
-+ *             uint32_t data_size,
-+ *             VCHI_FLAGS_T flags,
-+ *             void *msg_handle
-+ *
-+ * Description: Thin wrapper to queue a message onto a connection
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+
-+vcos_static_assert(sizeof(VCHI_MSG_VECTOR_T) == sizeof(VCHIQ_ELEMENT_T));
-+vcos_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_base) == offsetof(VCHIQ_ELEMENT_T, data));
-+vcos_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_len) == offsetof(VCHIQ_ELEMENT_T, size));
-+
-+int32_t
-+vchi_msg_queuev( VCHI_SERVICE_HANDLE_T handle,
-+   VCHI_MSG_VECTOR_T * vector,
-+   uint32_t count,
-+   VCHI_FLAGS_T flags,
-+   void *msg_handle )
-+{
-+   VCHI_SERVICE_T *service = (VCHI_SERVICE_T *)handle;
-+   VCHIQ_QUEUE_MESSAGE_T args;
-+   int ret;
-+
-+   vcos_unused(msg_handle);
-+
-+   vcos_assert(flags == VCHI_FLAGS_BLOCK_UNTIL_QUEUED);
-+
-+   args.handle = service->handle;
-+   args.elements = (const VCHIQ_ELEMENT_T *)vector;
-+   args.count = count;
-+   RETRY(ret, ioctl(service->fd, VCHIQ_IOC_QUEUE_MESSAGE, &args));
-+
-+   return ret;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_held_msg_release
-+ *
-+ * Arguments:  VCHI_HELD_MSG_T *message
-+ *
-+ * Description: Routine to release a held message (after it has been read with vchi_msg_hold)
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+int32_t
-+vchi_held_msg_release( VCHI_HELD_MSG_T *message )
-+{
-+   int ret = -1;
-+
-+   if (message && message->message && !message->service)
-+   {
-+      free_msgbuf(message->message);
-+      ret = 0;
-+   }
-+
-+   return ret;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_msg_hold
-+ *
-+ * Arguments:  VCHI_SERVICE_HANDLE_T handle,
-+ *             void **data,
-+ *             uint32_t *msg_size,
-+ *             VCHI_FLAGS_T flags,
-+ *             VCHI_HELD_MSG_T *message_handle
-+ *
-+ * Description: Routine to return a pointer to the current message (to allow in place processing)
-+ *              The message is dequeued - don't forget to release the message using
-+ *              vchi_held_msg_release when you're finished
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+int32_t
-+vchi_msg_hold( VCHI_SERVICE_HANDLE_T handle,
-+   void **data,
-+   uint32_t *msg_size,
-+   VCHI_FLAGS_T flags,
-+   VCHI_HELD_MSG_T *message_handle )
-+{
-+   VCHI_SERVICE_T *service = (VCHI_SERVICE_T *)handle;
-+   int ret;
-+
-+   ret = fill_peek_buf(service, flags);
-+
-+   if (ret == 0)
-+   {
-+      *data = service->peek_buf;
-+      *msg_size = service->peek_size;
-+
-+      message_handle->message = service->peek_buf;
-+      message_handle->service = NULL;
-+
-+      service->peek_size = -1;
-+      service->peek_buf = NULL;
-+   }
-+
-+   return 0;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_initialise
-+ *
-+ * Arguments: VCHI_INSTANCE_T *instance_handle
-+ *            VCHI_CONNECTION_T **connections
-+ *            const uint32_t num_connections
-+ *
-+ * Description: Initialises the hardware but does not transmit anything
-+ *              When run as a Host App this will be called twice hence the need
-+ *              to malloc the state information
-+ *
-+ * Returns: 0 if successful, failure otherwise
-+ *
-+ ***********************************************************/
-+int32_t
-+vchi_initialise( VCHI_INSTANCE_T *instance_handle )
-+{
-+   VCHIQ_INSTANCE_T instance;
-+
-+   instance = vchiq_lib_init();
-+
-+   vcos_log_trace( "%s: returning instance handle %p", __func__, instance );
-+
-+   *instance_handle = (VCHI_INSTANCE_T)instance;
-+
-+   return (instance != NULL) ? 0 : -1;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_connect
-+ *
-+ * Arguments: VCHI_CONNECTION_T **connections
-+ *            const uint32_t num_connections
-+ *            VCHI_INSTANCE_T instance_handle )
-+ *
-+ * Description: Starts the command service on each connection,
-+ *              causing INIT messages to be pinged back and forth
-+ *
-+ * Returns: 0 if successful, failure otherwise
-+ *
-+ ***********************************************************/
-+int32_t
-+vchi_connect( VCHI_CONNECTION_T **connections,
-+   const uint32_t num_connections,
-+   VCHI_INSTANCE_T instance_handle )
-+{
-+   VCHIQ_STATUS_T status;
-+
-+   vcos_unused(connections);
-+   vcos_unused(num_connections);
-+
-+   status = vchiq_connect((VCHIQ_INSTANCE_T)instance_handle);
-+
-+   return (status == VCHIQ_SUCCESS) ? 0 : -1;
-+}
-+
-+
-+/***********************************************************
-+ * Name: vchi_disconnect
-+ *
-+ * Arguments: VCHI_INSTANCE_T instance_handle
-+ *
-+ * Description: Stops the command service on each connection,
-+ *              causing DE-INIT messages to be pinged back and forth
-+ *
-+ * Returns: 0 if successful, failure otherwise
-+ *
-+ ***********************************************************/
-+int32_t
-+vchi_disconnect( VCHI_INSTANCE_T instance_handle )
-+{
-+   VCHIQ_STATUS_T status;
-+   
-+   status = vchiq_shutdown((VCHIQ_INSTANCE_T)instance_handle);
-+
-+   return (status == VCHIQ_SUCCESS) ? 0 : -1;
-+}
-+
-+
-+/***********************************************************
-+ * Name: vchi_service_open
-+ * Name: vchi_service_create
-+ *
-+ * Arguments: VCHI_INSTANCE_T *instance_handle
-+ *            SERVICE_CREATION_T *setup,
-+ *            VCHI_SERVICE_HANDLE_T *handle
-+ *
-+ * Description: Routine to open a service
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+int32_t
-+vchi_service_open( VCHI_INSTANCE_T instance_handle,
-+   SERVICE_CREATION_T *setup,
-+   VCHI_SERVICE_HANDLE_T *handle )
-+{
-+   VCHIQ_SERVICE_PARAMS_T params;
-+   VCHIQ_STATUS_T status;
-+
-+   memset(&params, 0, sizeof(params));
-+   params.fourcc = setup->service_id;
-+   params.userdata = setup->callback_param;
-+
-+   status = create_service((VCHIQ_INSTANCE_T)instance_handle,
-+      &params,
-+      setup->callback,
-+      1/*open*/,
-+      (VCHIQ_SERVICE_HANDLE_T *)handle);
-+
-+   return (status == VCHIQ_SUCCESS) ? 0 : -1;
-+}
-+
-+int32_t
-+vchi_service_create( VCHI_INSTANCE_T instance_handle,
-+   SERVICE_CREATION_T *setup, VCHI_SERVICE_HANDLE_T *handle )
-+{
-+   VCHIQ_SERVICE_PARAMS_T params;
-+   VCHIQ_STATUS_T status;
-+
-+   memset(&params, 0, sizeof(params));
-+   params.fourcc = setup->service_id;
-+   params.userdata = setup->callback_param;
-+
-+   status = create_service((VCHIQ_INSTANCE_T)instance_handle,
-+      &params,
-+      setup->callback,
-+      0/*!open*/,
-+      (VCHIQ_SERVICE_HANDLE_T *)handle);
-+
-+   return (status == VCHIQ_SUCCESS) ? 0 : -1;
-+}
-+
-+int32_t
-+vchi_service_close( const VCHI_SERVICE_HANDLE_T handle )
-+{
-+   VCHI_SERVICE_T *service = (VCHI_SERVICE_T *)handle;
-+   int ret;
-+   RETRY(ret,ioctl(service->fd, VCHIQ_IOC_REMOVE_SERVICE, service->handle));
-+
-+   if (ret == 0)
-+      service->handle = VCHIQ_INVALID_HANDLE;
-+
-+   return ret;
-+}
-+
-+int32_t
-+vchi_service_destroy( const VCHI_SERVICE_HANDLE_T handle )
-+{
-+   VCHI_SERVICE_T *service = (VCHI_SERVICE_T *)handle;
-+   int ret;
-+   RETRY(ret,ioctl(service->fd, VCHIQ_IOC_REMOVE_SERVICE, service->handle));
-+
-+   if (ret == 0)
-+      service->handle = VCHIQ_INVALID_HANDLE;
-+
-+   return ret;
-+}
-+
-+/* ----------------------------------------------------------------------
-+ * read a uint32_t from buffer.
-+ * network format is defined to be little endian
-+ * -------------------------------------------------------------------- */
-+uint32_t
-+vchi_readbuf_uint32( const void *_ptr )
-+{
-+   const unsigned char *ptr = _ptr;
-+   return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
-+}
-+
-+/* ----------------------------------------------------------------------
-+ * write a uint32_t to buffer.
-+ * network format is defined to be little endian
-+ * -------------------------------------------------------------------- */
-+void
-+vchi_writebuf_uint32( void *_ptr, uint32_t value )
-+{
-+   unsigned char *ptr = _ptr;
-+   ptr[0] = (unsigned char)((value >> 0)  & 0xFF);
-+   ptr[1] = (unsigned char)((value >> 8)  & 0xFF);
-+   ptr[2] = (unsigned char)((value >> 16) & 0xFF);
-+   ptr[3] = (unsigned char)((value >> 24) & 0xFF);
-+}
-+
-+/* ----------------------------------------------------------------------
-+ * read a uint16_t from buffer.
-+ * network format is defined to be little endian
-+ * -------------------------------------------------------------------- */
-+uint16_t
-+vchi_readbuf_uint16( const void *_ptr )
-+{
-+   const unsigned char *ptr = _ptr;
-+   return ptr[0] | (ptr[1] << 8);
-+}
-+
-+/* ----------------------------------------------------------------------
-+ * write a uint16_t into the buffer.
-+ * network format is defined to be little endian
-+ * -------------------------------------------------------------------- */
-+void
-+vchi_writebuf_uint16( void *_ptr, uint16_t value )
-+{
-+   unsigned char *ptr = _ptr;
-+   ptr[0] = (value >> 0)  & 0xFF;
-+   ptr[1] = (value >> 8)  & 0xFF;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_service_use
-+ *
-+ * Arguments: const VCHI_SERVICE_HANDLE_T handle
-+ *
-+ * Description: Routine to increment refcount on a service
-+ *
-+ * Returns: void
-+ *
-+ ***********************************************************/
-+int32_t
-+vchi_service_use( const VCHI_SERVICE_HANDLE_T handle )
-+{
-+   VCHI_SERVICE_T *service = (VCHI_SERVICE_T *)handle;
-+   int ret;
-+   RETRY(ret,ioctl(service->fd, VCHIQ_IOC_USE_SERVICE, service->handle));
-+   return ret;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_service_release
-+ *
-+ * Arguments: const VCHI_SERVICE_HANDLE_T handle
-+ *
-+ * Description: Routine to decrement refcount on a service
-+ *
-+ * Returns: void
-+ *
-+ ***********************************************************/
-+int32_t vchi_service_release( const VCHI_SERVICE_HANDLE_T handle )
-+{
-+   VCHI_SERVICE_T *service = (VCHI_SERVICE_T *)handle;
-+   int ret;
-+   RETRY(ret,ioctl(service->fd, VCHIQ_IOC_RELEASE_SERVICE, service->handle));
-+   return ret;
-+}
-+
-+/*
-+ * Support functions
-+ */
-+
-+static VCHIQ_INSTANCE_T
-+vchiq_lib_init(void)
-+{
-+   static int mutex_initialised = 0;
-+   static VCOS_MUTEX_T vchiq_lib_mutex;
-+   VCHIQ_INSTANCE_T instance = &vchiq_instance;
-+
-+   vcos_global_lock();
-+   if (!mutex_initialised)
-+   {
-+      vcos_mutex_create(&vchiq_lib_mutex, "vchiq-init");
-+
-+      vcos_log_set_level( &vchiq_lib_log_category, vchiq_default_lib_log_level );
-+      vcos_log_register( "vchiq_lib", &vchiq_lib_log_category );
-+
-+      mutex_initialised = 1;
-+   }
-+   vcos_global_unlock();
-+
-+   vcos_mutex_lock(&vchiq_lib_mutex);
-+
-+   if (instance->initialised == 0)
-+   {
-+      instance->fd = open("/dev/vchiq", O_RDWR);
-+      if (instance->fd >= 0)
-+      {
-+         VCHIQ_GET_CONFIG_T args;
-+         VCHIQ_CONFIG_T config;
-+         int ret;
-+         args.config_size = sizeof(config);
-+         args.pconfig = &config;
-+         RETRY(ret, ioctl(instance->fd, VCHIQ_IOC_GET_CONFIG, &args));
-+         if ((ret == 0) && (config.version >= VCHIQ_VERSION_MIN) && (config.version_min <= VCHIQ_VERSION))
-+         {
-+            instance->used_services = 0;
-+            vcos_mutex_create(&instance->mutex, "VCHIQ instance");
-+            instance->initialised = 1;
-+         }
-+         else
-+         {
-+            if (ret == 0)
-+            {
-+               vcos_log_error("Incompatible VCHIQ library - driver version %d (min %d), library version %d (min %d)",
-+                  config.version, config.version_min, VCHIQ_VERSION, VCHIQ_VERSION_MIN);
-+            }
-+            else
-+            {
-+               vcos_log_error("Very incompatible VCHIQ library - cannot retrieve driver version");
-+            }
-+            close(instance->fd);
-+            instance = NULL;
-+         }
-+      }
-+      else
-+      {
-+         instance = NULL;
-+      }
-+   }
-+   else if (instance->initialised > 0)
-+   {
-+      instance->initialised++;
-+   }
-+
-+   vcos_mutex_unlock(&vchiq_lib_mutex);
-+
-+   return instance;
-+}
-+
-+static void *
-+completion_thread(void *arg)
-+{
-+   VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)arg;
-+   VCHIQ_AWAIT_COMPLETION_T args;
-+   VCHIQ_COMPLETION_DATA_T completions[8];
-+   void *msgbufs[8];
-+
-+   static const VCHI_CALLBACK_REASON_T vchiq_reason_to_vchi[] =
-+   {
-+      VCHI_CALLBACK_SERVICE_OPENED,        // VCHIQ_SERVICE_OPENED
-+      VCHI_CALLBACK_SERVICE_CLOSED,        // VCHIQ_SERVICE_CLOSED
-+      VCHI_CALLBACK_MSG_AVAILABLE,         // VCHIQ_MESSAGE_AVAILABLE
-+      VCHI_CALLBACK_BULK_SENT,             // VCHIQ_BULK_TRANSMIT_DONE
-+      VCHI_CALLBACK_BULK_RECEIVED,         // VCHIQ_BULK_RECEIVE_DONE
-+      VCHI_CALLBACK_BULK_TRANSMIT_ABORTED, // VCHIQ_BULK_TRANSMIT_ABORTED
-+      VCHI_CALLBACK_BULK_RECEIVE_ABORTED,  // VCHIQ_BULK_RECEIVE_ABORTED
-+   };
-+
-+   args.count = vcos_countof(completions);
-+   args.buf = completions;
-+   args.msgbufsize = MSGBUF_SIZE;
-+   args.msgbufcount = 0;
-+   args.msgbufs = msgbufs;
-+
-+   while (1)
-+   {
-+      int ret, i;
-+
-+      while ((unsigned int)args.msgbufcount < vcos_countof(msgbufs))
-+      {
-+         void *msgbuf = alloc_msgbuf();
-+         if (msgbuf)
-+         {
-+            msgbufs[args.msgbufcount++] = msgbuf;
-+         }
-+         else
-+         {
-+            fprintf(stderr, "vchiq_lib: failed to allocate a message buffer\n");
-+            vcos_demand(args.msgbufcount != 0);
-+         }
-+      }
-+
-+      RETRY(ret, ioctl(instance->fd, VCHIQ_IOC_AWAIT_COMPLETION, &args));
-+
-+      if (ret <= 0)
-+         break;
-+
-+      for (i = 0; i < ret; i++)
-+      {
-+         VCHIQ_COMPLETION_DATA_T *completion = &completions[i];
-+         VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)completion->service_userdata;
-+         if (service->base.callback)
-+         {
-+            vcos_log_trace( "callback(%x, %x, %x, %x)",
-+               completion->reason, (uint32_t)completion->header,
-+               (uint32_t)&service->base, (uint32_t)completion->bulk_userdata );
-+            service->base.callback(completion->reason, completion->header,
-+               &service->base, completion->bulk_userdata);
-+         }
-+         else if (service->vchi_callback)
-+         {
-+            VCHI_CALLBACK_REASON_T vchi_reason =
-+               vchiq_reason_to_vchi[completion->reason];
-+            service->vchi_callback(service->base.userdata, vchi_reason, completion->bulk_userdata);
-+         }
-+      }
-+   }
-+   return NULL;
-+}
-+
-+static VCHIQ_STATUS_T
-+create_service(VCHIQ_INSTANCE_T instance,
-+   const VCHIQ_SERVICE_PARAMS_T *params,
-+   VCHI_CALLBACK_T vchi_callback,
-+   int is_open,
-+   VCHIQ_SERVICE_HANDLE_T *pservice)
-+{
-+   VCHIQ_SERVICE_T *service = NULL;
-+   VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
-+   int i;
-+
-+   if (!is_valid_instance(instance))
-+      return VCHIQ_ERROR;
-+
-+   vcos_mutex_lock(&instance->mutex);
-+
-+   /* Find a free service */
-+   if (is_open)
-+   {
-+      /* Find a free service */
-+      for (i = 0; i < instance->used_services; i++)
-+      {
-+         if (instance->services[i].handle == VCHIQ_INVALID_HANDLE)
-+         {
-+            service = &instance->services[i];
-+            break;
-+         }
-+      }
-+   }
-+   else
-+   {
-+      for (i = (instance->used_services - 1); i >= 0; i--)
-+      {
-+         VCHIQ_SERVICE_T *srv = &instance->services[i];
-+         if (srv->handle == VCHIQ_INVALID_HANDLE)
-+         {
-+            service = srv;
-+         }
-+         else if (
-+            (srv->base.fourcc == params->fourcc) &&
-+            ((srv->base.callback != params->callback) ||
-+            (srv->vchi_callback != vchi_callback)))
-+         {
-+            /* There is another server using this fourcc which doesn't match */
-+            service = NULL;
-+            status = VCHIQ_ERROR;
-+            break;
-+         }
-+      }
-+   }
-+
-+   if (!service && (status == VCHIQ_SUCCESS) &&
-+      (instance->used_services < VCHIQ_MAX_INSTANCE_SERVICES))
-+      service = &instance->services[instance->used_services++];
-+
-+   if (service)
-+   {
-+      VCHIQ_CREATE_SERVICE_T args;
-+      int ret;
-+      service->base.fourcc = params->fourcc;
-+      service->base.callback = params->callback;
-+      service->vchi_callback = vchi_callback;
-+      service->base.userdata = params->userdata;
-+      service->fd = instance->fd;
-+      service->peek_size = -1;
-+      service->peek_buf = NULL;
-+
-+      args.params = *params;
-+      args.params.userdata = service;
-+      args.is_open = is_open;
-+      args.is_vchi = (params->callback == NULL);
-+      args.handle = -1; /* OUT parameter */
-+      RETRY(ret, ioctl(instance->fd, VCHIQ_IOC_CREATE_SERVICE, &args));
-+      if (ret == 0)
-+         service->handle = args.handle;
-+      else
-+         status = VCHIQ_ERROR;
-+   }
-+
-+   *pservice = (status == VCHIQ_SUCCESS) ? &service->base : NULL;
-+
-+   vcos_mutex_unlock(&instance->mutex);
-+
-+   return status;
-+}
-+
-+static int
-+fill_peek_buf(VCHI_SERVICE_T *service,
-+   VCHI_FLAGS_T flags)
-+{
-+   VCHIQ_DEQUEUE_MESSAGE_T args;
-+   int ret = 0;
-+
-+   vcos_assert(flags == VCHI_FLAGS_NONE || flags == VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE);
-+
-+   if (service->peek_size < 0)
-+   {
-+      if (!service->peek_buf)
-+         service->peek_buf = alloc_msgbuf();
-+
-+      if (service->peek_buf)
-+      {
-+         args.handle = service->handle;
-+         args.blocking = (flags == VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE);
-+         args.bufsize = MSGBUF_SIZE;
-+         args.buf = service->peek_buf;
-+
-+         RETRY(ret, ioctl(service->fd, VCHIQ_IOC_DEQUEUE_MESSAGE, &args));
-+
-+         if (ret >= 0)
-+         {
-+            service->peek_size = ret;
-+            ret = 0;
-+         }
-+         else
-+         {
-+            ret = -1;
-+         }
-+      }
-+      else
-+      {
-+         ret = -1;
-+      }
-+   }
-+
-+   return ret;
-+}
-+
-+
-+static void *
-+alloc_msgbuf(void)
-+{
-+   void *msgbuf;
-+   vcos_mutex_lock(&vchiq_lib_mutex);
-+   msgbuf = free_msgbufs;
-+   if (msgbuf)
-+      free_msgbufs = *(void **)msgbuf;
-+   vcos_mutex_unlock(&vchiq_lib_mutex);
-+   if (!msgbuf)
-+      msgbuf = malloc(MSGBUF_SIZE);
-+   return msgbuf;
-+}
-+
-+static void
-+free_msgbuf(void *buf)
-+{
-+   vcos_mutex_lock(&vchiq_lib_mutex);
-+   *(void **)buf = free_msgbufs;
-+   free_msgbufs = buf;
-+   vcos_mutex_unlock(&vchiq_lib_mutex);
-+}
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h
-@@ -0,0 +1,45 @@
-+/*****************************************************************************
-+* Copyright 2001 - 2010 Broadcom Corporation.  All rights reserved.
-+*
-+* Unless you and Broadcom execute a separate written software license
-+* agreement governing use of this software, this software is licensed to you
-+* under the terms of the GNU General Public License version 2, available at
-+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-+*
-+* Notwithstanding the above, under no circumstances may you combine this
-+* software in any way with any other Broadcom software provided under a
-+* license other than the GPL, without Broadcom's express prior written
-+* consent.
-+*****************************************************************************/
-+
-+#ifndef VCHIQ_MEMDRV_H
-+#define VCHIQ_MEMDRV_H
-+
-+/* ---- Include Files ----------------------------------------------------- */
-+
-+#include <linux/kernel.h>
-+#include "vchiq_if.h"
-+
-+/* ---- Constants and Types ---------------------------------------------- */
-+
-+typedef struct
-+{
-+    void                   *armSharedMemVirt;
-+    dma_addr_t              armSharedMemPhys;
-+    size_t                  armSharedMemSize;
-+
-+    void                   *vcSharedMemVirt;
-+    dma_addr_t              vcSharedMemPhys;
-+    size_t                  vcSharedMemSize;
-+
-+} VCHIQ_SHARED_MEM_INFO_T;
-+
-+/* ---- Variable Externs ------------------------------------------------- */
-+
-+/* ---- Function Prototypes ---------------------------------------------- */
-+
-+void vchiq_get_shared_mem_info( VCHIQ_SHARED_MEM_INFO_T *info );
-+
-+VCHIQ_STATUS_T vchiq_memdrv_initialise(void);
-+
-+#endif
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h
-@@ -0,0 +1,43 @@
-+/*
-+ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#ifndef VCHIQ_PAGELIST_H
-+#define VCHIQ_PAGELIST_H
-+
-+#ifndef PAGE_SIZE
-+#define PAGE_SIZE 4096
-+#endif
-+#define CACHE_LINE_SIZE 32
-+#define PAGELIST_WRITE 0
-+#define PAGELIST_READ 1
-+#define PAGELIST_READ_WITH_FRAGMENTS 2
-+
-+typedef struct pagelist_struct {
-+      unsigned long length;
-+      unsigned short type;
-+      unsigned short offset;
-+      unsigned long addrs[1]; /* N.B. 12 LSBs hold the number of following
-+                                 pages at consecutive addresses. */
-+} PAGELIST_T;
-+
-+typedef struct fragments_struct {
-+      char headbuf[CACHE_LINE_SIZE];
-+      char tailbuf[CACHE_LINE_SIZE];
-+} FRAGMENTS_T;
-+
-+#endif /* VCHIQ_PAGELIST_H */
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c
-@@ -0,0 +1,970 @@
-+/*
-+ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#include "interface/vchi/vchi.h"
-+#include "vchiq.h"
-+#include "vchiq_core.h"
-+
-+#include "vchiq_util.h"
-+
-+#include <stddef.h>
-+
-+#if defined(__KERNEL__)
-+#include <linux/module.h>
-+#endif
-+
-+#define vchiq_status_to_vchi(status) ((int32_t)status)
-+
-+typedef struct {
-+   VCHIQ_SERVICE_HANDLE_T handle;
-+
-+   VCHIU_QUEUE_T queue;
-+
-+   VCHI_CALLBACK_T callback;
-+   void *callback_param;
-+} SHIM_SERVICE_T;
-+
-+/* ----------------------------------------------------------------------
-+ * return pointer to the mphi message driver function table
-+ * -------------------------------------------------------------------- */
-+#ifdef WIN32
-+const VCHI_MESSAGE_DRIVER_T *
-+mphi_get_func_table( void )
-+{
-+   return NULL;
-+}
-+#endif
-+
-+/* ----------------------------------------------------------------------
-+ * return pointer to the mphi message driver function table
-+ * -------------------------------------------------------------------- */
-+const VCHI_MESSAGE_DRIVER_T *
-+vchi_mphi_message_driver_func_table( void )
-+{
-+   return NULL;
-+}
-+
-+/* ----------------------------------------------------------------------
-+ * return a pointer to the 'single' connection driver fops
-+ * -------------------------------------------------------------------- */
-+const VCHI_CONNECTION_API_T *
-+single_get_func_table( void )
-+{
-+   return NULL;
-+}
-+
-+VCHI_CONNECTION_T * vchi_create_connection( const VCHI_CONNECTION_API_T * function_table,
-+                                            const VCHI_MESSAGE_DRIVER_T * low_level)
-+{
-+   vcos_unused(function_table);
-+   vcos_unused(low_level);
-+   return NULL;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_msg_peek
-+ *
-+ * Arguments:  const VCHI_SERVICE_HANDLE_T handle,
-+ *             void **data,
-+ *             uint32_t *msg_size,
-+ *             VCHI_FLAGS_T flags
-+ *
-+ * Description: Routine to return a pointer to the current message (to allow in place processing)
-+ *              The message can be removed using vchi_msg_remove when you're finished
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+int32_t vchi_msg_peek( VCHI_SERVICE_HANDLE_T handle,
-+                       void **data,
-+                       uint32_t *msg_size,
-+                       VCHI_FLAGS_T flags )
-+{
-+   SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
-+   VCHIQ_HEADER_T *header;
-+
-+   vcos_assert(flags == VCHI_FLAGS_NONE || flags == VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE);
-+
-+   if (flags == VCHI_FLAGS_NONE)
-+      if (vchiu_queue_is_empty(&service->queue))
-+         return -1;
-+
-+   header = vchiu_queue_peek(&service->queue);
-+
-+   *data = header->data;
-+   *msg_size = header->size;
-+
-+   return 0;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_msg_remove
-+ *
-+ * Arguments:  const VCHI_SERVICE_HANDLE_T handle,
-+ *
-+ * Description: Routine to remove a message (after it has been read with vchi_msg_peek)
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+int32_t vchi_msg_remove( VCHI_SERVICE_HANDLE_T handle )
-+{
-+   SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
-+   VCHIQ_HEADER_T *header;
-+
-+   header = vchiu_queue_pop(&service->queue);
-+
-+   vchiq_release_message(service->handle, header);
-+
-+   return 0;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_msg_queue
-+ *
-+ * Arguments:  VCHI_SERVICE_HANDLE_T handle,
-+ *             const void *data,
-+ *             uint32_t data_size,
-+ *             VCHI_FLAGS_T flags,
-+ *             void *msg_handle,
-+ *
-+ * Description: Thin wrapper to queue a message onto a connection
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+int32_t vchi_msg_queue( VCHI_SERVICE_HANDLE_T handle,
-+                        const void * data,
-+                        uint32_t data_size,
-+                        VCHI_FLAGS_T flags,
-+                        void * msg_handle )
-+{
-+   SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
-+   VCHIQ_ELEMENT_T element = {data, data_size};
-+   VCHIQ_STATUS_T status;
-+
-+   vcos_unused(msg_handle);
-+
-+   vcos_assert(flags == VCHI_FLAGS_BLOCK_UNTIL_QUEUED);
-+
-+   status = vchiq_queue_message(service->handle, &element, 1);
-+
-+   // On some platforms, like linux kernel, vchiq_queue_message() may return
-+   // VCHIQ_RETRY, so we need to implment a retry mechanism since this
-+   // function is supposed to block until queued
-+   while ( status == VCHIQ_RETRY )
-+   {
-+      vcos_sleep( 1 );
-+      status = vchiq_queue_message(service->handle, &element, 1);
-+   }
-+
-+   return vchiq_status_to_vchi(status);
-+}
-+
-+/***********************************************************
-+ * Name: vchi_bulk_queue_receive
-+ *
-+ * Arguments:  VCHI_BULK_HANDLE_T handle,
-+ *             void *data_dst,
-+ *             const uint32_t data_size,
-+ *             VCHI_FLAGS_T flags
-+ *             void *bulk_handle
-+ *
-+ * Description: Routine to setup a rcv buffer
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+int32_t vchi_bulk_queue_receive( VCHI_SERVICE_HANDLE_T handle,
-+                                 void * data_dst,
-+                                 uint32_t data_size,
-+                                 VCHI_FLAGS_T flags,
-+                                 void * bulk_handle )
-+{
-+   SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
-+   VCHIQ_BULK_MODE_T mode;
-+   VCHIQ_STATUS_T status;
-+
-+   switch ((int)flags) {
-+   case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE | VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
-+      vcos_assert(service->callback);
-+      mode = VCHIQ_BULK_MODE_CALLBACK;
-+      break;
-+   case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE:
-+      mode = VCHIQ_BULK_MODE_BLOCKING;
-+      break;
-+   case VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
-+   case VCHI_FLAGS_NONE:
-+      mode = VCHIQ_BULK_MODE_NOCALLBACK;
-+      break;
-+   default:
-+      vcos_assert(0);
-+      return vchiq_status_to_vchi(VCHIQ_ERROR);
-+   }
-+
-+   status = vchiq_bulk_receive(service->handle, data_dst, data_size,
-+      bulk_handle, mode);
-+
-+   // On some platforms, like linux kernel, vchiq_bulk_receive() may return
-+   // VCHIQ_RETRY, so we need to implment a retry mechanism since this
-+   // function is supposed to block until queued
-+   while ( status == VCHIQ_RETRY )
-+   {
-+      vcos_sleep( 1 );
-+      status = vchiq_bulk_receive(service->handle, data_dst, data_size,
-+         bulk_handle, mode);
-+   }
-+
-+   return vchiq_status_to_vchi(status);
-+}
-+
-+/***********************************************************
-+ * Name: vchi_bulk_queue_receive_reloc
-+ *
-+ * Arguments:  VCHI_BULK_HANDLE_T handle,
-+ *             VCHI_MEM_HANDLE_T h
-+ *             uint32_t offset
-+ *             const uint32_t data_size,
-+ *             VCHI_FLAGS_T flags
-+ *             void *bulk_handle
-+ *
-+ * Description: Routine to setup a relocatable rcv buffer
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+int32_t vchi_bulk_queue_receive_reloc( const VCHI_SERVICE_HANDLE_T handle,
-+                                       VCHI_MEM_HANDLE_T h,
-+                                       uint32_t offset,
-+                                       uint32_t data_size,
-+                                       const VCHI_FLAGS_T flags,
-+                                       void * const bulk_handle )
-+{
-+   SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
-+   VCHIQ_BULK_MODE_T mode;
-+   VCHIQ_STATUS_T status;
-+
-+   switch ((int)flags) {
-+   case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE | VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
-+      vcos_assert(service->callback);
-+      mode = VCHIQ_BULK_MODE_CALLBACK;
-+      break;
-+   case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE:
-+      mode = VCHIQ_BULK_MODE_BLOCKING;
-+      break;
-+   case VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
-+   case VCHI_FLAGS_NONE:
-+      mode = VCHIQ_BULK_MODE_NOCALLBACK;
-+      break;
-+   default:
-+      vcos_assert(0);
-+      return vchiq_status_to_vchi(VCHIQ_ERROR);
-+   }
-+
-+   status = vchiq_bulk_receive_handle(service->handle, h, (void*)offset,
-+      data_size, bulk_handle, mode);
-+
-+   // On some platforms, like linux kernel, vchiq_bulk_receive_handle() may
-+   // return VCHIQ_RETRY, so we need to implment a retry mechanism since
-+   // this function is supposed to block until queued
-+   while ( status == VCHIQ_RETRY )
-+   {
-+      vcos_sleep( 1 );
-+      status = vchiq_bulk_receive_handle(service->handle, h, (void*)offset,
-+         data_size, bulk_handle, mode);
-+   }
-+
-+   return vchiq_status_to_vchi(status);
-+}
-+
-+/***********************************************************
-+ * Name: vchi_bulk_queue_transmit
-+ *
-+ * Arguments:  VCHI_BULK_HANDLE_T handle,
-+ *             const void *data_src,
-+ *             uint32_t data_size,
-+ *             VCHI_FLAGS_T flags,
-+ *             void *bulk_handle
-+ *
-+ * Description: Routine to transmit some data
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+int32_t vchi_bulk_queue_transmit( VCHI_SERVICE_HANDLE_T handle,
-+                                  const void * data_src,
-+                                  uint32_t data_size,
-+                                  VCHI_FLAGS_T flags,
-+                                  void * bulk_handle )
-+{
-+   SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
-+   VCHIQ_BULK_MODE_T mode;
-+   VCHIQ_STATUS_T status;
-+
-+   switch ((int)flags) {
-+   case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE | VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
-+      vcos_assert(service->callback);
-+      mode = VCHIQ_BULK_MODE_CALLBACK;
-+      break;
-+   case VCHI_FLAGS_BLOCK_UNTIL_DATA_READ:
-+   case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE:
-+      mode = VCHIQ_BULK_MODE_BLOCKING;
-+      break;
-+   case VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
-+   case VCHI_FLAGS_NONE:
-+      mode = VCHIQ_BULK_MODE_NOCALLBACK;
-+      break;
-+   default:
-+      vcos_assert(0);
-+      return vchiq_status_to_vchi(VCHIQ_ERROR);
-+   }
-+
-+   status = vchiq_bulk_transmit(service->handle, data_src, data_size,
-+      bulk_handle, mode);
-+
-+   // On some platforms, like linux kernel, vchiq_bulk_transmit() may return
-+   // VCHIQ_RETRY, so we need to implment a retry mechanism since this
-+   // function is supposed to block until queued
-+   while ( status == VCHIQ_RETRY )
-+   {
-+      vcos_sleep( 1 );
-+      status = vchiq_bulk_transmit(service->handle, data_src, data_size,
-+         bulk_handle, mode);
-+   }
-+
-+   return vchiq_status_to_vchi(status);
-+}
-+
-+/***********************************************************
-+ * Name: vchi_bulk_queue_transmit_reloc
-+ *
-+ * Arguments:  VCHI_BULK_HANDLE_T handle,
-+ *             VCHI_MEM_HANDLE_T h_src,
-+ *             uint32_t offset,
-+ *             uint32_t data_size,
-+ *             VCHI_FLAGS_T flags,
-+ *             void *bulk_handle
-+ *
-+ * Description: Routine to transmit some data from a relocatable buffer
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+
-+int32_t vchi_bulk_queue_transmit_reloc( VCHI_SERVICE_HANDLE_T handle,
-+                                        VCHI_MEM_HANDLE_T h_src,
-+                                        uint32_t offset,
-+                                        uint32_t data_size,
-+                                        VCHI_FLAGS_T flags,
-+                                        void * const bulk_handle )
-+{
-+   SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
-+   VCHIQ_BULK_MODE_T mode;
-+   VCHIQ_STATUS_T status;
-+
-+   switch ((int)flags) {
-+   case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE | VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
-+      vcos_assert(service->callback);
-+      mode = VCHIQ_BULK_MODE_CALLBACK;
-+      break;
-+   case VCHI_FLAGS_BLOCK_UNTIL_DATA_READ:
-+   case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE:
-+      mode = VCHIQ_BULK_MODE_BLOCKING;
-+      break;
-+   case VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
-+   case VCHI_FLAGS_NONE:
-+      mode = VCHIQ_BULK_MODE_NOCALLBACK;
-+      break;
-+   default:
-+      vcos_assert(0);
-+      return vchiq_status_to_vchi(VCHIQ_ERROR);
-+   }
-+
-+   status = vchiq_bulk_transmit_handle(service->handle, h_src, (void*)offset,
-+      data_size, bulk_handle, mode);
-+
-+   // On some platforms, like linux kernel, vchiq_bulk_transmit_handle() may
-+   // return VCHIQ_RETRY, so we need to implment a retry mechanism since this
-+   // function is supposed to block until queued
-+   while ( status == VCHIQ_RETRY )
-+   {
-+      vcos_sleep( 1 );
-+      status = vchiq_bulk_transmit_handle(service->handle, h_src, (void*)offset,
-+         data_size, bulk_handle, mode);
-+   }
-+
-+   return vchiq_status_to_vchi(status);
-+}
-+
-+/***********************************************************
-+ * Name: vchi_msg_dequeue
-+ *
-+ * Arguments:  VCHI_SERVICE_HANDLE_T handle,
-+ *             void *data,
-+ *             uint32_t max_data_size_to_read,
-+ *             uint32_t *actual_msg_size
-+ *             VCHI_FLAGS_T flags
-+ *
-+ * Description: Routine to dequeue a message into the supplied buffer
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+int32_t vchi_msg_dequeue( VCHI_SERVICE_HANDLE_T handle,
-+                          void *data,
-+                          uint32_t max_data_size_to_read,
-+                          uint32_t *actual_msg_size,
-+                          VCHI_FLAGS_T flags )
-+{
-+   SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
-+   VCHIQ_HEADER_T *header;
-+
-+   vcos_assert(flags == VCHI_FLAGS_NONE || flags == VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE);
-+
-+   if (flags == VCHI_FLAGS_NONE)
-+      if (vchiu_queue_is_empty(&service->queue))
-+         return -1;
-+
-+   header = vchiu_queue_pop(&service->queue);
-+
-+   memcpy(data, header->data, header->size < max_data_size_to_read ? header->size : max_data_size_to_read);
-+
-+   *actual_msg_size = header->size;
-+
-+   vchiq_release_message(service->handle, header);
-+
-+   return 0;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_msg_queuev
-+ *
-+ * Arguments:  VCHI_SERVICE_HANDLE_T handle,
-+ *             const void *data,
-+ *             uint32_t data_size,
-+ *             VCHI_FLAGS_T flags,
-+ *             void *msg_handle
-+ *
-+ * Description: Thin wrapper to queue a message onto a connection
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+
-+vcos_static_assert(sizeof(VCHI_MSG_VECTOR_T) == sizeof(VCHIQ_ELEMENT_T));
-+vcos_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_base) == offsetof(VCHIQ_ELEMENT_T, data));
-+vcos_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_len) == offsetof(VCHIQ_ELEMENT_T, size));
-+
-+int32_t vchi_msg_queuev( VCHI_SERVICE_HANDLE_T handle,
-+                         VCHI_MSG_VECTOR_T * vector,
-+                         uint32_t count,
-+                         VCHI_FLAGS_T flags,
-+                         void *msg_handle )
-+{
-+   SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
-+
-+   vcos_unused(msg_handle);
-+
-+   vcos_assert(flags == VCHI_FLAGS_BLOCK_UNTIL_QUEUED);
-+
-+   return vchiq_status_to_vchi(vchiq_queue_message(service->handle, (const VCHIQ_ELEMENT_T *)vector, count));
-+}
-+
-+#ifdef USE_MEMMGR
-+
-+/***********************************************************
-+ * Name: vchi_msg_queuev_ex
-+ *
-+ * Arguments:  VCHI_SERVICE_HANDLE_T handle,
-+ *             VCHI_MSG_VECTOR_EX_T *vector
-+ *             uint32_t count
-+ *             VCHI_FLAGS_T flags,
-+ *             void *msg_handle
-+ *
-+ * Description: Thin wrapper to queue an array of messages onto a connection
-+ * Supports resolving MEM_HANDLE's at last possible moment to avoid deadlocks.
-+ *
-+ * Currently just a shim, so deadlocks are still possible!
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+int32_t vchi_msg_queuev_ex( const VCHI_SERVICE_HANDLE_T handle,
-+                            VCHI_MSG_VECTOR_EX_T * const vector,
-+                            const uint32_t count,
-+                            const VCHI_FLAGS_T flags,
-+                            void * const msg_handle )
-+{
-+   int32_t success = -1;
-+   // For now, we don't actually support sending anything other than
-+   // a pointer, so handles have to be patched up; this is likely
-+   // to cause deadlocks. This code is not designed to be either
-+   // pretty, efficient, or deadlock-free.
-+
-+   #define max_vecs 16
-+   VCHI_MSG_VECTOR_T copy[max_vecs];
-+   const uint8_t *orig[max_vecs];
-+
-+   int i;
-+   vcos_unused(msg_handle);
-+
-+   if (count > sizeof(copy)/sizeof(copy[0]))
-+   {
-+      vcos_assert(0);
-+      return -1;
-+   }
-+
-+   for (i=0; i<count; i++)
-+   {
-+      VCHI_MSG_VECTOR_EX_T *v = vector+i;
-+
-+      switch (vector[i].type)
-+      {
-+      case VCHI_VEC_POINTER:
-+         copy[i].vec_base = v->u.ptr.vec_base;
-+         copy[i].vec_len =  v->u.ptr.vec_len;
-+         break;
-+      case VCHI_VEC_HANDLE:
-+         vcos_assert(v->u.handle.offset+v->u.handle.vec_len <= mem_get_size(v->u.handle.handle));
-+         copy[i].vec_base = (uint8_t*)mem_lock(v->u.handle.handle) + v->u.handle.offset;
-+         orig[i] = copy[i].vec_base;
-+         copy[i].vec_len = v->u.handle.vec_len;
-+         break;
-+      case VCHI_VEC_LIST:
-+         vcos_assert(0); // FIXME: implement this
-+         break;
-+      default:
-+         vcos_assert(0);
-+      }
-+   }
-+   success = vchi_msg_queuev( handle,
-+                              copy,
-+                              count,
-+                              flags &~ VCHI_FLAGS_INTERNAL,
-+                              msg_handle );
-+   if (vcos_verify(success == 0))
-+   {
-+      // now we need to patch up the vectors if any have been only partially consumed, and
-+      // unlock memory handles.
-+   
-+      for (i=0; i<count; i++)
-+      {
-+         VCHI_MSG_VECTOR_EX_T *v = vector+i;
-+
-+         switch (vector[i].type)
-+         {
-+         case VCHI_VEC_POINTER:
-+            if (flags & VCHI_FLAGS_ALLOW_PARTIAL)
-+            {
-+               v->u.ptr.vec_base = copy[i].vec_base;
-+               v->u.ptr.vec_len  = copy[i].vec_len;
-+            }
-+            break;
-+         case VCHI_VEC_HANDLE:
-+            mem_unlock(v->u.handle.handle);
-+            if (flags & VCHI_FLAGS_ALLOW_PARTIAL)
-+            {
-+               const uint8_t *old = orig[i];
-+               uint32_t change = (const uint8_t*)copy[i].vec_base-old;
-+               v->u.handle.offset += change;
-+               v->u.handle.vec_len -= change;
-+            }
-+            break;
-+         default:
-+            vcos_assert(0);
-+         }
-+      }
-+   }
-+
-+   return vchiq_status_to_vchi(success);
-+}
-+
-+#endif
-+
-+/***********************************************************
-+ * Name: vchi_held_msg_release
-+ *
-+ * Arguments:  VCHI_HELD_MSG_T *message
-+ *
-+ * Description: Routine to release a held message (after it has been read with vchi_msg_hold)
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+int32_t vchi_held_msg_release( VCHI_HELD_MSG_T *message )
-+{
-+   vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)message->service, (VCHIQ_HEADER_T *)message->message);
-+
-+   return 0;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_msg_hold
-+ *
-+ * Arguments:  VCHI_SERVICE_HANDLE_T handle,
-+ *             void **data,
-+ *             uint32_t *msg_size,
-+ *             VCHI_FLAGS_T flags,
-+ *             VCHI_HELD_MSG_T *message_handle
-+ *
-+ * Description: Routine to return a pointer to the current message (to allow in place processing)
-+ *              The message is dequeued - don't forget to release the message using
-+ *              vchi_held_msg_release when you're finished
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+int32_t vchi_msg_hold( VCHI_SERVICE_HANDLE_T handle,
-+                       void **data,
-+                       uint32_t *msg_size,
-+                       VCHI_FLAGS_T flags,
-+                       VCHI_HELD_MSG_T *message_handle )
-+{
-+   SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
-+   VCHIQ_HEADER_T *header;
-+
-+   vcos_assert(flags == VCHI_FLAGS_NONE || flags == VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE);
-+
-+   if (flags == VCHI_FLAGS_NONE)
-+      if (vchiu_queue_is_empty(&service->queue))
-+         return -1;
-+
-+   header = vchiu_queue_pop(&service->queue);
-+
-+   *data = header->data;
-+   *msg_size = header->size;
-+
-+   message_handle->service = (struct opaque_vchi_service_t *)service->handle;
-+   message_handle->message = header;
-+
-+   return 0;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_initialise
-+ *
-+ * Arguments: VCHI_INSTANCE_T *instance_handle
-+ *            VCHI_CONNECTION_T **connections
-+ *            const uint32_t num_connections
-+ *
-+ * Description: Initialises the hardware but does not transmit anything
-+ *              When run as a Host App this will be called twice hence the need
-+ *              to malloc the state information
-+ *
-+ * Returns: 0 if successful, failure otherwise
-+ *
-+ ***********************************************************/
-+
-+int32_t vchi_initialise( VCHI_INSTANCE_T *instance_handle )
-+{
-+   VCHIQ_INSTANCE_T instance;
-+   VCHIQ_STATUS_T status;
-+
-+   status = vchiq_initialise(&instance);
-+
-+   *instance_handle = (VCHI_INSTANCE_T)instance;
-+
-+   return vchiq_status_to_vchi(status);
-+}
-+
-+/***********************************************************
-+ * Name: vchi_connect
-+ *
-+ * Arguments: VCHI_CONNECTION_T **connections
-+ *            const uint32_t num_connections
-+ *            VCHI_INSTANCE_T instance_handle )
-+ *
-+ * Description: Starts the command service on each connection,
-+ *              causing INIT messages to be pinged back and forth
-+ *
-+ * Returns: 0 if successful, failure otherwise
-+ *
-+ ***********************************************************/
-+int32_t vchi_connect( VCHI_CONNECTION_T **connections,
-+                      const uint32_t num_connections,
-+                      VCHI_INSTANCE_T instance_handle )
-+{
-+   VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
-+
-+   vcos_unused(connections);
-+   vcos_unused(num_connections);
-+
-+   return vchiq_connect(instance);
-+}
-+
-+
-+/***********************************************************
-+ * Name: vchi_disconnect
-+ *
-+ * Arguments: VCHI_INSTANCE_T instance_handle
-+ *
-+ * Description: Stops the command service on each connection,
-+ *              causing DE-INIT messages to be pinged back and forth
-+ *
-+ * Returns: 0 if successful, failure otherwise
-+ *
-+ ***********************************************************/
-+int32_t vchi_disconnect( VCHI_INSTANCE_T instance_handle )
-+{
-+   VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
-+   return vchiq_status_to_vchi(vchiq_shutdown(instance));
-+}
-+
-+
-+/***********************************************************
-+ * Name: vchi_service_open
-+ * Name: vchi_service_create
-+ *
-+ * Arguments: VCHI_INSTANCE_T *instance_handle
-+ *            SERVICE_CREATION_T *setup,
-+ *            VCHI_SERVICE_HANDLE_T *handle
-+ *
-+ * Description: Routine to open a service
-+ *
-+ * Returns: int32_t - success == 0
-+ *
-+ ***********************************************************/
-+
-+static VCHIQ_STATUS_T shim_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, VCHIQ_SERVICE_HANDLE_T handle, void *bulk_user)
-+{
-+   SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)VCHIQ_GET_SERVICE_USERDATA(handle);
-+
-+   switch (reason) {
-+   case VCHIQ_MESSAGE_AVAILABLE:
-+      vchiu_queue_push(&service->queue, header);
-+
-+      if (service->callback)
-+         service->callback(service->callback_param, VCHI_CALLBACK_MSG_AVAILABLE, NULL);
-+      break;
-+   case VCHIQ_BULK_TRANSMIT_DONE:
-+      if (service->callback)
-+         service->callback(service->callback_param, VCHI_CALLBACK_BULK_SENT, bulk_user);
-+      break;
-+   case VCHIQ_BULK_RECEIVE_DONE:
-+      if (service->callback)
-+         service->callback(service->callback_param, VCHI_CALLBACK_BULK_RECEIVED, bulk_user);
-+      break;
-+   case VCHIQ_SERVICE_CLOSED:
-+      if (service->callback)
-+         service->callback(service->callback_param, VCHI_CALLBACK_SERVICE_CLOSED, NULL);
-+      break;
-+   case VCHIQ_SERVICE_OPENED:
-+      /* No equivalent VCHI reason */
-+      break;
-+   case VCHIQ_BULK_TRANSMIT_ABORTED:
-+      if (service->callback)
-+         service->callback(service->callback_param, VCHI_CALLBACK_BULK_TRANSMIT_ABORTED, bulk_user);
-+      break;
-+   case VCHIQ_BULK_RECEIVE_ABORTED:
-+      if (service->callback)
-+         service->callback(service->callback_param, VCHI_CALLBACK_BULK_RECEIVE_ABORTED, bulk_user);
-+      break;
-+   default:
-+      vcos_assert(0);
-+      break;
-+   }
-+
-+   return VCHIQ_SUCCESS;
-+}
-+
-+static SHIM_SERVICE_T *service_alloc(VCHIQ_INSTANCE_T instance,
-+                                     SERVICE_CREATION_T *setup)
-+{
-+   SHIM_SERVICE_T *service = vcos_calloc(1, sizeof(SHIM_SERVICE_T), "vchiq_shim");
-+
-+   vcos_unused(instance);
-+
-+   if (service)
-+   {
-+      if (vchiu_queue_init(&service->queue, 64))
-+      {
-+         service->callback = setup->callback;
-+         service->callback_param = setup->callback_param;
-+      }
-+      else
-+      {
-+         vcos_free(service);
-+         service = NULL;
-+      }
-+   }
-+
-+   return service;
-+}
-+
-+static void service_free(SHIM_SERVICE_T *service)
-+{
-+   if (service)
-+   {
-+      vchiu_queue_delete(&service->queue);
-+      vcos_free((void*)service);
-+   }
-+}
-+
-+int32_t vchi_service_open( VCHI_INSTANCE_T instance_handle,
-+                           SERVICE_CREATION_T *setup,
-+                           VCHI_SERVICE_HANDLE_T *handle)
-+{
-+   VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
-+   SHIM_SERVICE_T *service = service_alloc(instance, setup);
-+   if (service)
-+   {
-+      VCHIQ_STATUS_T status = vchiq_open_service(instance, setup->service_id, shim_callback, service, &service->handle);
-+      if (status != VCHIQ_SUCCESS)
-+      {
-+         service_free(service);
-+         service = NULL;
-+      }
-+   }
-+
-+   *handle = (VCHI_SERVICE_HANDLE_T)service;
-+
-+   return (service != NULL) ? 0 : -1;
-+}
-+
-+int32_t vchi_service_create( VCHI_INSTANCE_T instance_handle,
-+                             SERVICE_CREATION_T *setup,
-+                             VCHI_SERVICE_HANDLE_T *handle )
-+{
-+   VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
-+   SHIM_SERVICE_T *service = service_alloc(instance, setup);
-+   if (service)
-+   {
-+      VCHIQ_STATUS_T status = vchiq_add_service(instance, setup->service_id, shim_callback, service, &service->handle);
-+      if (status != VCHIQ_SUCCESS)
-+      {
-+         service_free(service);
-+         service = NULL;
-+      }
-+   }
-+
-+   *handle = (VCHI_SERVICE_HANDLE_T)service;
-+
-+   return (service != NULL) ? 0 : -1;
-+}
-+
-+int32_t vchi_service_close( const VCHI_SERVICE_HANDLE_T handle )
-+{
-+   vcos_unused(handle);
-+
-+   // YTI??
-+   return 0;
-+}
-+
-+/* ----------------------------------------------------------------------
-+ * read a uint32_t from buffer.
-+ * network format is defined to be little endian
-+ * -------------------------------------------------------------------- */
-+uint32_t
-+vchi_readbuf_uint32( const void *_ptr )
-+{
-+   const unsigned char *ptr = _ptr;
-+   return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
-+}
-+
-+/* ----------------------------------------------------------------------
-+ * write a uint32_t to buffer.
-+ * network format is defined to be little endian
-+ * -------------------------------------------------------------------- */
-+void
-+vchi_writebuf_uint32( void *_ptr, uint32_t value )
-+{
-+   unsigned char *ptr = _ptr;
-+   ptr[0] = (unsigned char)((value >> 0)  & 0xFF);
-+   ptr[1] = (unsigned char)((value >> 8)  & 0xFF);
-+   ptr[2] = (unsigned char)((value >> 16) & 0xFF);
-+   ptr[3] = (unsigned char)((value >> 24) & 0xFF);
-+}
-+
-+/* ----------------------------------------------------------------------
-+ * read a uint16_t from buffer.
-+ * network format is defined to be little endian
-+ * -------------------------------------------------------------------- */
-+uint16_t
-+vchi_readbuf_uint16( const void *_ptr )
-+{
-+   const unsigned char *ptr = _ptr;
-+   return ptr[0] | (ptr[1] << 8);
-+}
-+
-+/* ----------------------------------------------------------------------
-+ * write a uint16_t into the buffer.
-+ * network format is defined to be little endian
-+ * -------------------------------------------------------------------- */
-+void
-+vchi_writebuf_uint16( void *_ptr, uint16_t value )
-+{
-+   unsigned char *ptr = _ptr;
-+   ptr[0] = (value >> 0)  & 0xFF;
-+   ptr[1] = (value >> 8)  & 0xFF;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_service_use
-+ *
-+ * Arguments: const VCHI_SERVICE_HANDLE_T handle
-+ *
-+ * Description: Routine to increment refcount on a service
-+ *
-+ * Returns: void
-+ *
-+ ***********************************************************/
-+int32_t vchi_service_use( const VCHI_SERVICE_HANDLE_T handle )
-+{
-+   int32_t ret = -1;
-+   SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
-+   if(service)
-+   {
-+      ret = vchiq_status_to_vchi(vchiq_use_service(service->handle));
-+   }
-+   return ret;
-+}
-+
-+/***********************************************************
-+ * Name: vchi_service_release
-+ *
-+ * Arguments: const VCHI_SERVICE_HANDLE_T handle
-+ *
-+ * Description: Routine to decrement refcount on a service
-+ *
-+ * Returns: void
-+ *
-+ ***********************************************************/
-+int32_t vchi_service_release( const VCHI_SERVICE_HANDLE_T handle )
-+{
-+   int32_t ret = -1;
-+   SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
-+   if(service)
-+   {
-+      ret = vchiq_status_to_vchi(vchiq_release_service(service->handle));
-+   }
-+   return ret;
-+}
-+
-+#if defined(__KERNEL__)
-+EXPORT_SYMBOL(vchi_initialise);
-+EXPORT_SYMBOL(vchi_connect);
-+EXPORT_SYMBOL(vchi_bulk_queue_transmit);
-+EXPORT_SYMBOL(vchi_msg_dequeue);
-+EXPORT_SYMBOL(vchi_msg_queue);
-+EXPORT_SYMBOL(vchi_msg_queuev);
-+EXPORT_SYMBOL(vchi_service_close);
-+EXPORT_SYMBOL(vchi_service_open);
-+EXPORT_SYMBOL(vchi_service_create);
-+EXPORT_SYMBOL(vchi_service_use);
-+EXPORT_SYMBOL(vchi_service_release);
-+#endif
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c
-@@ -0,0 +1,97 @@
-+/*
-+ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#include "vchiq_util.h"
-+
-+#if !defined(__KERNEL__)
-+#include <stdlib.h>
-+#endif
-+
-+static __inline int is_pow2(int i)
-+{
-+  return i && !(i & (i - 1));
-+}
-+
-+int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size)
-+{
-+   vcos_assert(is_pow2(size));
-+
-+   queue->size = size;
-+   queue->read = 0;
-+   queue->write = 0;
-+
-+   vcos_event_create(&queue->pop, "vchiu");
-+   vcos_event_create(&queue->push, "vchiu");
-+
-+   queue->storage = vcos_malloc(size * sizeof(VCHIQ_HEADER_T *), VCOS_FUNCTION);
-+   if (queue->storage == NULL)
-+   {
-+      vchiu_queue_delete(queue);
-+      return 0;
-+   }
-+   return 1;
-+}
-+
-+void vchiu_queue_delete(VCHIU_QUEUE_T *queue)
-+{
-+   vcos_event_delete(&queue->pop);
-+   vcos_event_delete(&queue->push);
-+   if (queue->storage != NULL)
-+      vcos_free(queue->storage);
-+}
-+
-+int vchiu_queue_is_empty(VCHIU_QUEUE_T *queue)
-+{
-+   return queue->read == queue->write;
-+}
-+
-+void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header)
-+{
-+   while (queue->write == queue->read + queue->size)
-+      vcos_event_wait(&queue->pop);
-+
-+   queue->storage[queue->write & (queue->size - 1)] = header;
-+
-+   queue->write++;
-+
-+   vcos_event_signal(&queue->push);
-+}
-+
-+VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue)
-+{
-+   while (queue->write == queue->read)
-+      vcos_event_wait(&queue->push);
-+
-+   return queue->storage[queue->read & (queue->size - 1)];
-+}
-+
-+VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue)
-+{
-+   VCHIQ_HEADER_T *header;
-+
-+   while (queue->write == queue->read)
-+      vcos_event_wait(&queue->push);
-+
-+   header = queue->storage[queue->read & (queue->size - 1)];
-+
-+   queue->read++;
-+
-+   vcos_event_signal(&queue->pop);
-+
-+   return header;
-+}
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h
-@@ -0,0 +1,47 @@
-+/*
-+ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#ifndef VCHIQ_UTIL_H
-+#define VCHIQ_UTIL_H
-+
-+#include "vchiq_if.h"
-+#include "interface/vcos/vcos.h"
-+
-+typedef struct {
-+   int size;
-+   int read;
-+   int write;
-+
-+   VCOS_EVENT_T pop;
-+   VCOS_EVENT_T push;
-+
-+   VCHIQ_HEADER_T **storage;
-+} VCHIU_QUEUE_T;
-+
-+extern int  vchiu_queue_init(VCHIU_QUEUE_T *queue, int size);
-+extern void vchiu_queue_delete(VCHIU_QUEUE_T *queue);
-+
-+extern int vchiu_queue_is_empty(VCHIU_QUEUE_T *queue);
-+
-+extern void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header);
-+
-+extern VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue);
-+extern VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue);
-+
-+#endif
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_cmd.c
-@@ -0,0 +1,681 @@
-+/*****************************************************************************
-+* Copyright 2009 - 2011 Broadcom Corporation.  All rights reserved.
-+*
-+* Unless you and Broadcom execute a separate written software license
-+* agreement governing use of this software, this software is licensed to you
-+* under the terms of the GNU General Public License version 2, available at
-+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-+*
-+* Notwithstanding the above, under no circumstances may you combine this
-+* software in any way with any other Broadcom software provided under a
-+* license other than the GPL, without Broadcom's express prior written
-+* consent.
-+*****************************************************************************/
-+
-+/***************************************************************************** 
-+* 
-+*    This file provides a generic command line interface which allows
-+*    vcos internals to be manipulated and/or displayed.
-+*  
-+*****************************************************************************/
-+
-+/* ---- Include Files ---------------------------------------------------- */
-+
-+#include "interface/vcos/vcos.h"
-+
-+#ifdef HAVE_VCOS_VERSION
-+#include "interface/vcos/vcos_build_info.h"
-+#endif
-+
-+        #ifdef _VIDEOCORE
-+#include vcfw/logging/logging.h
-+#endif
-+
-+/* ---- Public Variables ------------------------------------------------- */
-+
-+/* ---- Private Constants and Types -------------------------------------- */
-+
-+#define  VCOS_LOG_CATEGORY (&vcos_cmd_log_category)
-+VCOS_LOG_CAT_T vcos_cmd_log_category;
-+
-+/* ---- Private Variables ------------------------------------------------ */
-+
-+static struct VCOS_CMD_GLOBALS_T
-+{
-+    VCOS_MUTEX_T    lock;
-+    VCOS_ONCE_T     initialized;
-+
-+    unsigned        num_cmd_entries;
-+    unsigned        num_cmd_alloc;
-+    VCOS_CMD_T     *cmd_entry;
-+
-+    VCOS_LOG_CAT_T *log_category;
-+} cmd_globals;
-+
-+/* ---- Private Function Prototypes -------------------------------------- */
-+
-+static VCOS_STATUS_T help_cmd( VCOS_CMD_PARAM_T *param );
-+
-+/* ---- Functions  ------------------------------------------------------- */
-+
-+/***************************************************************************** 
-+*
-+*   Walks through the commands looking for a particular command
-+*
-+*****************************************************************************/
-+
-+static VCOS_CMD_T *find_cmd( VCOS_CMD_T *cmd_entry, const char *name )
-+{
-+    VCOS_CMD_T   *scan_entry = cmd_entry;
-+
-+    while ( scan_entry->name != NULL )
-+    {
-+        if ( vcos_strcmp( scan_entry->name, name ) == 0 )
-+        {
-+            return scan_entry;
-+        }
-+        scan_entry++;
-+    }
-+
-+    return NULL;
-+}
-+
-+/***************************************************************************** 
-+*
-+*   Saves away 
-+*   each line individually.
-+*
-+*****************************************************************************/
-+
-+void vcos_cmd_always_log_output( VCOS_LOG_CAT_T *log_category )
-+{
-+    cmd_globals.log_category = log_category;
-+}
-+
-+/***************************************************************************** 
-+*
-+*   Walks through a buffer containing newline separated lines, and logs
-+*   each line individually.
-+*
-+*****************************************************************************/
-+
-+static void cmd_log_results( VCOS_CMD_PARAM_T *param )
-+{
-+    char    *start;
-+    char    *end;
-+
-+    start = end = param->result_buf;
-+
-+    while ( *start != '\0' )
-+    {
-+        while (( *end != '\0' ) && ( *end != '\n' ))
-+            end++;
-+
-+        if ( *end == '\n' )
-+        {
-+            *end++ = '\0';
-+        }
-+
-+        if ( cmd_globals.log_category != NULL )
-+        {
-+            if ( vcos_is_log_enabled( cmd_globals.log_category, VCOS_LOG_INFO ))
-+            {
-+                vcos_log_impl( cmd_globals.log_category, VCOS_LOG_INFO, "%s", start );
-+            }
-+        }
-+        else
-+        {
-+            vcos_log_info( "%s", start );
-+        }
-+
-+        start = end;
-+    }
-+
-+    /* Since we logged the buffer, reset the pointer back to the beginning. */
-+
-+    param->result_ptr = param->result_buf;
-+    param->result_buf[0] = '\0';
-+}
-+
-+/***************************************************************************** 
-+*
-+*   Since we may have limited output space, we create a generic routine
-+*   which tries to use the result space, but will switch over to using
-+*   logging if the output is too large.
-+*
-+*****************************************************************************/
-+
-+void vcos_cmd_vprintf( VCOS_CMD_PARAM_T *param, const char *fmt, va_list args )
-+{
-+    int     bytes_written;
-+    int     bytes_remaining;
-+
-+    bytes_remaining = (int)(param->result_size - ( param->result_ptr - param->result_buf ));
-+
-+    bytes_written = vcos_vsnprintf( param->result_ptr, bytes_remaining, fmt, args );
-+
-+    if ( cmd_globals.log_category != NULL )
-+    {
-+        /* We're going to log each line as we encounter it. If the buffer
-+         * doesn't end in a newline, then we'll wait for one first.
-+         */
-+
-+        if ( (( bytes_written + 1 ) >= bytes_remaining ) 
-+        ||   ( param->result_ptr[ bytes_written - 1 ] == '\n' ))
-+        {
-+            cmd_log_results( param );
-+        }
-+        else
-+        {
-+            param->result_ptr += bytes_written;
-+        }
-+    }
-+    else
-+    {
-+        if (( bytes_written + 1 ) >= bytes_remaining )
-+        {
-+            /* Output doesn't fit - switch over to logging */
-+
-+            param->use_log = 1;
-+
-+            *param->result_ptr = '\0';  /* Zap the partial line that didn't fit above. */
-+
-+            cmd_log_results( param );   /* resets result_ptr */
-+
-+            bytes_written = vcos_vsnprintf( param->result_ptr, bytes_remaining, fmt, args );
-+        }
-+        param->result_ptr += bytes_written;
-+    }
-+}
-+
-+/***************************************************************************** 
-+*
-+*   Prints the output.
-+*
-+*****************************************************************************/
-+
-+void vcos_cmd_printf( VCOS_CMD_PARAM_T *param, const char *fmt, ... )
-+{
-+    va_list args;
-+
-+    va_start( args, fmt );
-+    vcos_cmd_vprintf( param, fmt, args );
-+    va_end( args );
-+}
-+
-+/***************************************************************************** 
-+*
-+*   Prints the arguments which were on the command line prior to ours.
-+*
-+*****************************************************************************/
-+
-+static void print_argument_prefix( VCOS_CMD_PARAM_T *param )
-+{
-+    int arg_idx;
-+
-+    for ( arg_idx = 0; &param->argv_orig[arg_idx] != param->argv; arg_idx++ )
-+    {
-+        vcos_cmd_printf( param, "%s ", param->argv_orig[arg_idx] );
-+    }
-+}
-+
-+/***************************************************************************** 
-+*
-+*   Prints an error message, prefixed by the command chain required to get
-+*   to where we're at.
-+*
-+*****************************************************************************/
-+
-+void vcos_cmd_error( VCOS_CMD_PARAM_T *param, const char *fmt, ... )
-+{
-+    va_list args;
-+
-+    print_argument_prefix( param );
-+
-+    va_start( args, fmt );
-+    vcos_cmd_vprintf( param, fmt, args );
-+    va_end( args );
-+    vcos_cmd_printf( param, "\n" );
-+}
-+
-+/****************************************************************************
-+*
-+*  usage - prints command usage for an array of commands.
-+*
-+***************************************************************************/
-+
-+static void usage( VCOS_CMD_PARAM_T *param, VCOS_CMD_T *cmd_entry )
-+{
-+    int         cmd_idx;
-+    int         nameWidth = 0;
-+    int         argsWidth = 0;
-+    VCOS_CMD_T *scan_entry;
-+
-+    vcos_cmd_printf( param, "Usage: " );
-+    print_argument_prefix( param );
-+    vcos_cmd_printf( param, "command [args ...]\n" );
-+    vcos_cmd_printf( param, "\n" );
-+    vcos_cmd_printf( param, "Where command is one of the following:\n" );
-+
-+    for ( cmd_idx = 0; cmd_entry[cmd_idx].name != NULL; cmd_idx++ )
-+    {
-+        int aw;
-+        int nw;
-+
-+        scan_entry = &cmd_entry[cmd_idx];
-+
-+        nw = vcos_strlen( scan_entry->name );
-+        aw = vcos_strlen( scan_entry->args );
-+
-+        if ( nw > nameWidth )
-+        {
-+            nameWidth = nw;
-+        }
-+        if ( aw > argsWidth )
-+        {
-+            argsWidth = aw;
-+        }
-+    }
-+
-+    for ( cmd_idx = 0; cmd_entry[cmd_idx].name != NULL; cmd_idx++ )
-+    {
-+        scan_entry = &cmd_entry[cmd_idx];
-+
-+        vcos_cmd_printf( param, "  %-*s %-*s - %s\n", 
-+                    nameWidth, scan_entry->name,
-+                    argsWidth, scan_entry->args,
-+                    scan_entry->descr );
-+    }
-+}
-+
-+/****************************************************************************
-+*
-+*  Prints the usage for the current command.
-+*
-+***************************************************************************/
-+
-+void vcos_cmd_usage( VCOS_CMD_PARAM_T *param )
-+{
-+    VCOS_CMD_T *cmd_entry;
-+
-+    cmd_entry = param->cmd_entry;
-+
-+    if ( cmd_entry->sub_cmd_entry != NULL )
-+    {
-+        /* This command is command with sub-commands */
-+
-+        usage( param, param->cmd_entry->sub_cmd_entry );
-+    }
-+    else
-+    {
-+        vcos_cmd_printf( param, "Usage: " );
-+        print_argument_prefix( param );
-+        vcos_cmd_printf( param, "%s - %s\n",
-+                         param->cmd_entry->args,
-+                         param->cmd_entry->descr );
-+    }
-+}
-+
-+/***************************************************************************** 
-+*
-+*   Command to print out the help
-+* 
-+*   This help command is only called from the main menu.
-+* 
-+*****************************************************************************/
-+
-+static VCOS_STATUS_T help_cmd( VCOS_CMD_PARAM_T *param )
-+{
-+    VCOS_CMD_T  *found_entry;
-+
-+#if 0
-+    {
-+        int arg_idx;
-+
-+        vcos_log_trace( "%s: argc = %d", __func__, param->argc );
-+        for ( arg_idx = 0; arg_idx < param->argc; arg_idx++ )
-+        {
-+            vcos_log_trace( "%s:  argv[%d] = '%s'", __func__, arg_idx, param->argv[arg_idx] );
-+        }
-+    }
-+#endif
-+
-+    /* If there is an argument after the word help, then we want to print
-+     * help for that command.
-+     */
-+
-+    if ( param->argc == 1 )
-+    {
-+        if ( param->cmd_parent_entry == cmd_globals.cmd_entry )
-+        {
-+            /* Bare help - print the command usage for the root */
-+
-+            usage( param, cmd_globals.cmd_entry );
-+            return VCOS_SUCCESS;
-+        }
-+
-+        /* For all other cases help requires an argument */
-+            
-+        vcos_cmd_error( param, "%s requires an argument", param->argv[0] );
-+        return VCOS_EINVAL;
-+    }
-+
-+    /* We were given an argument. */
-+
-+    if (( found_entry = find_cmd( param->cmd_parent_entry, param->argv[1] )) != NULL )
-+    {
-+        /* Make it look like the command that was specified is the one that's
-+         * currently running
-+         */
-+
-+        param->cmd_entry = found_entry;
-+        param->argv[0] = param->argv[1];
-+        param->argv++;
-+        param->argc--;
-+
-+        vcos_cmd_usage( param );
-+        return VCOS_SUCCESS;
-+    }
-+
-+    vcos_cmd_error( param, "- unrecognized command: '%s'", param->argv[1] );
-+    return VCOS_ENOENT;
-+}
-+
-+/***************************************************************************** 
-+*
-+*   Command to print out the version/build information.
-+*
-+*****************************************************************************/
-+
-+#ifdef HAVE_VCOS_VERSION
-+
-+static VCOS_STATUS_T version_cmd( VCOS_CMD_PARAM_T *param )
-+{
-+    static const char* copyright = "Copyright (c) 2011 Broadcom";
-+
-+    vcos_cmd_printf( param, "%s %s\n%s\nversion %s\n",
-+                     vcos_get_build_date(),
-+                     vcos_get_build_time(),
-+                     copyright,
-+                     vcos_get_build_version() );
-+
-+    return VCOS_SUCCESS;
-+}
-+
-+#endif
-+
-+/*****************************************************************************
-+*
-+*   Internal commands
-+*
-+*****************************************************************************/
-+
-+static VCOS_CMD_T cmd_help    = { "help",    "[command]", help_cmd,    NULL, "Prints command help information" };
-+
-+#ifdef HAVE_VCOS_VERSION
-+static VCOS_CMD_T cmd_version = { "version", "",          version_cmd, NULL, "Prints build/version information" };
-+#endif
-+
-+/***************************************************************************** 
-+*
-+*   Walks the command table and executes the commands
-+*
-+*****************************************************************************/
-+
-+static VCOS_STATUS_T execute_cmd( VCOS_CMD_PARAM_T *param, VCOS_CMD_T *cmd_entry )
-+{
-+    const char     *cmdStr;
-+    VCOS_CMD_T     *found_entry;
-+
-+#if 0
-+    {
-+        int arg_idx;
-+
-+        vcos_cmd_printf( param, "%s: argc = %d", __func__, param->argc );
-+        for ( arg_idx = 0; arg_idx < param->argc; arg_idx++ )
-+        {
-+            vcos_cmd_printf( param, " argv[%d] = '%s'", arg_idx, param->argv[arg_idx] );
-+        }
-+        vcos_cmd_printf( param, "\n" );
-+    }
-+#endif
-+
-+    if ( param->argc <= 1 )
-+    {
-+        /* No command specified */
-+
-+        vcos_cmd_error( param, "%s - no command specified", param->argv[0] );
-+        return VCOS_EINVAL;
-+    }
-+
-+    /* argv[0] is the command/program that caused us to get invoked, so we strip
-+     * it off.
-+     */
-+
-+    param->argc--;
-+    param->argv++;
-+    param->cmd_parent_entry = cmd_entry;
-+
-+    /* Not the help command, scan for the command and execute it. */
-+
-+    cmdStr = param->argv[0];
-+
-+    if (( found_entry = find_cmd( cmd_entry, cmdStr )) != NULL )
-+    {
-+        if ( found_entry->sub_cmd_entry != NULL )
-+        {
-+            return execute_cmd( param, found_entry->sub_cmd_entry );
-+        }
-+
-+        param->cmd_entry = found_entry;
-+        return found_entry->cmd_fn( param );
-+    }
-+
-+    /* Unrecognized command - check to see if it was the help command */
-+
-+    if ( vcos_strcmp( cmdStr, cmd_help.name ) == 0 )
-+    {
-+        return help_cmd( param );
-+    }
-+
-+    vcos_cmd_error( param, "- unrecognized command: '%s'", cmdStr );
-+    return VCOS_ENOENT;
-+}
-+
-+/***************************************************************************** 
-+*
-+*   Initializes the command line parser.
-+*
-+*****************************************************************************/
-+
-+static void vcos_cmd_init( void )
-+{
-+    vcos_mutex_create( &cmd_globals.lock, "vcos_cmd" );
-+
-+    cmd_globals.num_cmd_entries = 0;
-+    cmd_globals.num_cmd_alloc = 0;
-+    cmd_globals.cmd_entry = NULL;
-+}
-+
-+/***************************************************************************** 
-+*
-+*   Command line processor.
-+*
-+*****************************************************************************/
-+
-+VCOS_STATUS_T vcos_cmd_execute( int argc, char **argv, size_t result_size, char *result_buf )
-+{
-+    VCOS_STATUS_T       rc = VCOS_EINVAL;
-+    VCOS_CMD_PARAM_T    param;
-+
-+    vcos_once( &cmd_globals.initialized, vcos_cmd_init );
-+
-+    param.argc = argc;
-+    param.argv = param.argv_orig = argv;
-+
-+    param.use_log = 0;
-+    param.result_size = result_size;
-+    param.result_ptr = result_buf;
-+    param.result_buf = result_buf;
-+
-+      result_buf[0] = '\0';
-+
-+    vcos_mutex_lock( &cmd_globals.lock );
-+
-+    rc = execute_cmd( &param, cmd_globals.cmd_entry );
-+
-+    if ( param.use_log )
-+    {
-+        cmd_log_results( &param );
-+        vcos_snprintf( result_buf, result_size, "results logged" );
-+    }
-+    else
-+    if ( cmd_globals.log_category != NULL )
-+    {
-+        if ( result_buf[0] != '\0' )
-+        {
-+            /* There is a partial line still buffered. */
-+
-+            vcos_cmd_printf( &param, "\n" );
-+        }
-+    }
-+
-+    vcos_mutex_unlock( &cmd_globals.lock );
-+
-+    return rc;
-+}
-+
-+/***************************************************************************** 
-+*
-+*   Registers a command entry with the command line processor
-+*
-+*****************************************************************************/
-+
-+VCOS_STATUS_T vcos_cmd_register( VCOS_CMD_T *cmd_entry )
-+{
-+    VCOS_STATUS_T   rc;
-+    VCOS_UNSIGNED   new_num_cmd_alloc;
-+    VCOS_CMD_T     *new_cmd_entry;
-+    VCOS_CMD_T     *old_cmd_entry;
-+    VCOS_CMD_T     *scan_entry;
-+
-+    vcos_once( &cmd_globals.initialized, vcos_cmd_init );
-+
-+    vcos_assert( cmd_entry != NULL );
-+    vcos_assert( cmd_entry->name != NULL );
-+
-+    vcos_log_trace( "%s: cmd '%s'", __FUNCTION__, cmd_entry->name );
-+
-+    vcos_assert( cmd_entry->args != NULL );
-+    vcos_assert(( cmd_entry->cmd_fn != NULL ) || ( cmd_entry->sub_cmd_entry != NULL ));
-+    vcos_assert( cmd_entry->descr != NULL );
-+
-+    /* We expect vcos_cmd_init to be called before vcos_logging_init, so we
-+     * need to defer registering our logging category until someplace
-+     * like right here.
-+     */
-+
-+    if ( vcos_cmd_log_category.name == NULL )
-+    {
-+        /*
-+         * If you're using the command interface, you pretty much always want
-+         * log messages from this file to show up. So we change the default
-+         * from ERROR to be the more reasonable INFO level.
-+         */
-+
-+        vcos_log_set_level(&vcos_cmd_log_category, VCOS_LOG_INFO);
-+        vcos_log_register("vcos_cmd", &vcos_cmd_log_category);
-+
-+        /* We register a help command so that it shows up in the usage. */
-+
-+        vcos_cmd_register( &cmd_help );
-+#ifdef HAVE_VCOS_VERSION
-+        vcos_cmd_register( &cmd_version );
-+#endif
-+    }
-+
-+    vcos_mutex_lock( &cmd_globals.lock );
-+
-+    if ( cmd_globals.num_cmd_entries >= cmd_globals.num_cmd_alloc )
-+    {
-+        if ( cmd_globals.num_cmd_alloc == 0 )
-+        {
-+            /* We haven't allocated a table yet */
-+        }
-+
-+        /* The number 8 is rather arbitrary. */
-+
-+        new_num_cmd_alloc = cmd_globals.num_cmd_alloc + 8;
-+
-+        /* The + 1 is to ensure that we always have a NULL entry at the end. */
-+
-+        new_cmd_entry = (VCOS_CMD_T *)vcos_calloc( new_num_cmd_alloc + 1, sizeof( *cmd_entry ), "vcos_cmd_entries" );
-+        if ( new_cmd_entry == NULL )
-+        {
-+            rc = VCOS_ENOMEM;
-+            goto out;
-+        }
-+        memcpy( new_cmd_entry, cmd_globals.cmd_entry, cmd_globals.num_cmd_entries * sizeof( *cmd_entry ));
-+        cmd_globals.num_cmd_alloc = new_num_cmd_alloc;
-+        old_cmd_entry = cmd_globals.cmd_entry;
-+        cmd_globals.cmd_entry = new_cmd_entry;
-+        vcos_free( old_cmd_entry );
-+    }
-+
-+    if ( cmd_globals.num_cmd_entries == 0 )
-+    {
-+        /* This is the first command being registered */
-+
-+        cmd_globals.cmd_entry[0] = *cmd_entry;
-+    }
-+    else
-+    {
-+        /* Keep the list in alphabetical order. We start at the end and work backwards
-+         * shuffling entries up one until we find an insertion point.
-+         */
-+
-+        for ( scan_entry = &cmd_globals.cmd_entry[cmd_globals.num_cmd_entries - 1];
-+              scan_entry >= cmd_globals.cmd_entry; scan_entry-- )
-+        {
-+            if ( vcos_strcmp( cmd_entry->name, scan_entry->name ) > 0 )
-+            {
-+                /* We found an insertion point. */
-+
-+                break;
-+            }
-+
-+            scan_entry[1] = scan_entry[0];
-+        }
-+        scan_entry[1] = *cmd_entry;
-+    }
-+    cmd_globals.num_cmd_entries++;
-+
-+    rc = VCOS_SUCCESS;
-+
-+out:
-+
-+    vcos_mutex_unlock( &cmd_globals.lock );
-+    return rc;
-+}
-+
-+/***************************************************************************** 
-+*
-+*   Registers multiple commands.
-+*
-+*****************************************************************************/
-+
-+VCOS_STATUS_T vcos_cmd_register_multiple( VCOS_CMD_T *cmd_entry )
-+{
-+    VCOS_STATUS_T   status;
-+
-+    while ( cmd_entry->name != NULL )
-+    {
-+        if (( status = vcos_cmd_register( cmd_entry )) != VCOS_SUCCESS )
-+        {
-+            return status;
-+        }
-+        cmd_entry++;
-+    }
-+    return VCOS_SUCCESS;
-+}
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_common.h
-@@ -0,0 +1,76 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - common postamble code
-+=============================================================================*/
-+
-+/** \file
-+  *
-+  * Postamble code included by the platform-specific header files
-+  */
-+
-+#define VCOS_THREAD_PRI_DEFAULT VCOS_THREAD_PRI_NORMAL
-+
-+#if !defined(VCOS_THREAD_PRI_INCREASE)
-+#error Which way to thread priorities go?
-+#endif
-+
-+#if VCOS_THREAD_PRI_INCREASE < 0
-+/* smaller numbers are higher priority */
-+#define VCOS_THREAD_PRI_LESS(x) ((x)<VCOS_THREAD_PRI_MAX?(x)+1:VCOS_THREAD_PRI_MAX)
-+#define VCOS_THREAD_PRI_MORE(x) ((x)>VCOS_THREAD_PRI_MIN?(x)-1:VCOS_THREAD_PRI_MIN)
-+#else
-+/* bigger numbers are lower priority */
-+#define VCOS_THREAD_PRI_MORE(x) ((x)<VCOS_THREAD_PRI_MAX?(x)+1:VCOS_THREAD_PRI_MAX)
-+#define VCOS_THREAD_PRI_LESS(x) ((x)>VCOS_THREAD_PRI_MIN?(x)-1:VCOS_THREAD_PRI_MIN)
-+#endif
-+
-+/* Convenience for Brits: */
-+#define VCOS_APPLICATION_INITIALISE VCOS_APPLICATION_INITIALIZE
-+
-+/*
-+ * Check for constant definitions
-+ */
-+#ifndef VCOS_TICKS_PER_SECOND
-+#error VCOS_TICKS_PER_SECOND not defined
-+#endif
-+
-+#if !defined(VCOS_THREAD_PRI_MIN) || !defined(VCOS_THREAD_PRI_MAX)
-+#error Priority range not defined
-+#endif
-+
-+#if !defined(VCOS_THREAD_PRI_HIGHEST) || !defined(VCOS_THREAD_PRI_LOWEST) || !defined(VCOS_THREAD_PRI_NORMAL)
-+#error Priority ordering not defined
-+#endif
-+
-+#if !defined(VCOS_CAN_SET_STACK_ADDR)
-+#error Can stack addresses be set on this platform? Please set this macro to either 0 or 1.
-+#endif
-+
-+#if (_VCOS_AFFINITY_CPU0|_VCOS_AFFINITY_CPU1) & (~_VCOS_AFFINITY_MASK) 
-+#error _VCOS_AFFINITY_CPUxxx values are not consistent with _VCOS_AFFINITY_MASK
-+#endif
-+
-+/** Append to the end of a singly-linked queue, O(1). Works with
-+  * any structure where list has members 'head' and 'tail' and
-+  * item has a 'next' pointer.
-+  */
-+#define VCOS_QUEUE_APPEND_TAIL(list, item) {\
-+   (item)->next = NULL;\
-+   if (!(list)->head) {\
-+      (list)->head = (list)->tail = (item); \
-+   } else {\
-+      (list)->tail->next = (item); \
-+      (list)->tail = (item); \
-+   } \
-+}
-+
-+#ifndef VCOS_HAVE_TIMER
-+VCOSPRE_ void VCOSPOST_ vcos_timer_init(void);
-+#endif
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_blockpool.h
-@@ -0,0 +1,260 @@
-+/*=============================================================================
-+Copyright (c) 2011 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - event flags implemented via a semaphore
-+=============================================================================*/
-+
-+#ifndef VCOS_GENERIC_BLOCKPOOL_H
-+#define VCOS_GENERIC_BLOCKPOOL_H
-+
-+/**
-+  * \file
-+  *
-+  * This provides a generic, thread safe implementation of a VCOS block pool
-+  * fixed size memory allocator.
-+  */
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+
-+/** Bits 0 to (VCOS_BLOCKPOOL_SUBPOOL_BITS - 1) are used to store the
-+ * subpool id. */
-+#define VCOS_BLOCKPOOL_SUBPOOL_BITS 3
-+#define VCOS_BLOCKPOOL_MAX_SUBPOOLS (1 << VCOS_BLOCKPOOL_SUBPOOL_BITS)
-+
-+/* Make zero an invalid handle at the cost of decreasing the maximum
-+ * number of blocks (2^28) by 1. Alternatively, a spare bit could be
-+ * used to indicated valid blocks but there are likely to be better
-+ * uses for spare bits. e.g. allowing more subpools
-+ */
-+#define INDEX_OFFSET 1
-+
-+#define VCOS_BLOCKPOOL_HANDLE_GET_INDEX(h) \
-+   (((h) >> VCOS_BLOCKPOOL_SUBPOOL_BITS) - INDEX_OFFSET)
-+
-+#define VCOS_BLOCKPOOL_HANDLE_GET_SUBPOOL(h) \
-+   ((h) & ((1 << VCOS_BLOCKPOOL_SUBPOOL_BITS) - 1))
-+
-+#define VCOS_BLOCKPOOL_HANDLE_CREATE(i,s) \
-+   ((((i) + INDEX_OFFSET) << VCOS_BLOCKPOOL_SUBPOOL_BITS) | (s))
-+
-+#define VCOS_BLOCKPOOL_INVALID_HANDLE 0
-+
-+typedef struct VCOS_BLOCKPOOL_HEADER_TAG
-+{
-+   /* Blocks either refer to to the pool if they are allocated
-+    * or the free list if they are available.
-+    */
-+   union {
-+   struct VCOS_BLOCKPOOL_HEADER_TAG *next;
-+   struct VCOS_BLOCKPOOL_SUBPOOL_TAG* subpool;
-+   } owner;
-+} VCOS_BLOCKPOOL_HEADER_T;
-+
-+typedef struct VCOS_BLOCKPOOL_SUBPOOL_TAG
-+{
-+   /** VCOS_BLOCKPOOL_SUBPOOL_MAGIC */
-+   uint32_t magic;
-+   VCOS_BLOCKPOOL_HEADER_T* free_list;
-+   /* The start of the pool memory */
-+   void *mem;
-+   /* Address of the first block header */
-+   void *start;
-+   /** The number of blocks in this sub-pool */
-+   VCOS_UNSIGNED num_blocks;
-+   /** Current number of available blocks in this sub-pool */
-+   VCOS_UNSIGNED available_blocks;
-+   /** Pointers to the pool that owns this sub-pool */
-+   struct VCOS_BLOCKPOOL_TAG* owner;
-+   /** Define properties such as memory ownership */
-+   uint32_t flags;
-+} VCOS_BLOCKPOOL_SUBPOOL_T;
-+
-+typedef struct VCOS_BLOCKPOOL_TAG
-+{
-+   /** VCOS_BLOCKPOOL_MAGIC */
-+   uint32_t magic;
-+   /** Thread safety for Alloc, Free, Delete, Stats */
-+   VCOS_MUTEX_T mutex;
-+   /** The size of the block data */
-+   size_t block_data_size;
-+   /** Block size inc overheads */
-+   size_t block_size;
-+   /** Name for debugging */
-+   const char *name;
-+   /* The number of subpools that may be used */
-+   VCOS_UNSIGNED num_subpools;
-+   /** Number of blocks in each dynamically allocated subpool */
-+   VCOS_UNSIGNED num_extension_blocks;
-+   /** Array of subpools. Subpool zero is is not deleted until the pool is
-+    * destroed. If the index of the pool is < num_subpools and
-+    * subpool[index.mem] is null then the subpool entry is valid but
-+    * "not currently allocated" */
-+   VCOS_BLOCKPOOL_SUBPOOL_T subpools[VCOS_BLOCKPOOL_MAX_SUBPOOLS];
-+} VCOS_BLOCKPOOL_T;
-+
-+#define VCOS_BLOCKPOOL_ROUND_UP(x,s)   (((x) + ((s) - 1)) & ~((s) - 1))
-+/**
-+ * Calculates the size in bytes required for a block pool containing
-+ * num_blocks of size block_size plus any overheads.
-+ *
-+ * The block pool header (VCOS_BLOCKPOOL_T) is allocated separately
-+ *
-+ * Overheads:
-+ * block_size + header must be a multiple of sizeof(void*)
-+ * The start of the first block may need to be up to wordsize - 1 bytes
-+ * into the given buffer because statically allocated buffers within structures
-+ * are not guaranteed to be word aligned.
-+ */
-+#define VCOS_BLOCKPOOL_SIZE(num_blocks, block_size) \
-+   ((VCOS_BLOCKPOOL_ROUND_UP((block_size) + sizeof(VCOS_BLOCKPOOL_HEADER_T), \
-+                             sizeof(void*)) * (num_blocks)) + sizeof(void*))
-+
-+/**
-+ * Sanity check to verify whether a handle is potentially a blockpool handle
-+ * when the pool pointer is not available.
-+ *
-+ * If the pool pointer is availabe use vcos_blockpool_elem_to_handle instead.
-+ *
-+ * @param handle       the handle to verify
-+ * @param max_blocks   the expected maximum number of block in the pool
-+ *                     that the handle belongs to.
-+ */
-+#define VCOS_BLOCKPOOL_IS_VALID_HANDLE_FORMAT(handle, max_blocks) \
-+    ((handle) != VCOS_BLOCKPOOL_INVALID_HANDLE \
-+     && VCOS_BLOCKPOOL_HANDLE_GET_INDEX((handle)) < (max_blocks))
-+
-+VCOSPRE_
-+   VCOS_STATUS_T VCOSPOST_ vcos_generic_blockpool_init(VCOS_BLOCKPOOL_T *pool,
-+      VCOS_UNSIGNED num_blocks, VCOS_UNSIGNED block_size,
-+      void *start, VCOS_UNSIGNED pool_size, const char *name);
-+
-+VCOSPRE_
-+   VCOS_STATUS_T VCOSPOST_ vcos_generic_blockpool_create_on_heap(
-+         VCOS_BLOCKPOOL_T *pool, VCOS_UNSIGNED num_blocks,
-+         VCOS_UNSIGNED block_size, const char *name);
-+
-+VCOSPRE_
-+   VCOS_STATUS_T VCOSPOST_ vcos_generic_blockpool_extend(VCOS_BLOCKPOOL_T *pool,
-+         VCOS_UNSIGNED num_extensions, VCOS_UNSIGNED num_blocks);
-+
-+VCOSPRE_ void VCOSPOST_ *vcos_generic_blockpool_alloc(VCOS_BLOCKPOOL_T *pool);
-+
-+VCOSPRE_ void VCOSPOST_ *vcos_generic_blockpool_calloc(VCOS_BLOCKPOOL_T *pool);
-+
-+VCOSPRE_ void VCOSPOST_ vcos_generic_blockpool_free(void *block);
-+
-+VCOSPRE_
-+   VCOS_UNSIGNED VCOSPOST_ vcos_generic_blockpool_available_count(
-+         VCOS_BLOCKPOOL_T *pool);
-+
-+VCOSPRE_
-+   VCOS_UNSIGNED VCOSPOST_ vcos_generic_blockpool_used_count(
-+         VCOS_BLOCKPOOL_T *pool);
-+
-+VCOSPRE_ void VCOSPOST_ vcos_generic_blockpool_delete(VCOS_BLOCKPOOL_T *pool);
-+
-+VCOSPRE_ uint32_t VCOSPOST_ vcos_generic_blockpool_elem_to_handle(void *block);
-+
-+VCOSPRE_ void VCOSPOST_
-+   *vcos_generic_blockpool_elem_from_handle(
-+         VCOS_BLOCKPOOL_T *pool, uint32_t handle);
-+
-+VCOSPRE_ uint32_t VCOSPOST_
-+   vcos_generic_blockpool_is_valid_elem(
-+         VCOS_BLOCKPOOL_T *pool, const void *block);
-+#if defined(VCOS_INLINE_BODIES)
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_blockpool_init(VCOS_BLOCKPOOL_T *pool,
-+      VCOS_UNSIGNED num_blocks, VCOS_UNSIGNED block_size,
-+      void *start, VCOS_UNSIGNED pool_size, const char *name)
-+{
-+   return vcos_generic_blockpool_init(pool, num_blocks, block_size,
-+         start, pool_size, name);
-+}
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_blockpool_create_on_heap(VCOS_BLOCKPOOL_T *pool,
-+      VCOS_UNSIGNED num_blocks, VCOS_UNSIGNED block_size, const char *name)
-+{
-+   return vcos_generic_blockpool_create_on_heap(
-+         pool, num_blocks, block_size, name);
-+}
-+
-+VCOS_INLINE_IMPL
-+   VCOS_STATUS_T VCOSPOST_ vcos_blockpool_extend(VCOS_BLOCKPOOL_T *pool,
-+         VCOS_UNSIGNED num_extensions, VCOS_UNSIGNED num_blocks)
-+{
-+    return vcos_generic_blockpool_extend(pool, num_extensions, num_blocks);
-+}
-+
-+VCOS_INLINE_IMPL
-+void *vcos_blockpool_alloc(VCOS_BLOCKPOOL_T *pool)
-+{
-+   return vcos_generic_blockpool_alloc(pool);
-+}
-+
-+VCOS_INLINE_IMPL
-+void *vcos_blockpool_calloc(VCOS_BLOCKPOOL_T *pool)
-+{
-+   return vcos_generic_blockpool_calloc(pool);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_blockpool_free(void *block)
-+{
-+   vcos_generic_blockpool_free(block);
-+}
-+
-+VCOS_INLINE_IMPL
-+VCOS_UNSIGNED vcos_blockpool_available_count(VCOS_BLOCKPOOL_T *pool)
-+{
-+   return vcos_generic_blockpool_available_count(pool);
-+}
-+
-+VCOS_INLINE_IMPL
-+VCOS_UNSIGNED vcos_blockpool_used_count(VCOS_BLOCKPOOL_T *pool)
-+{
-+   return vcos_generic_blockpool_used_count(pool);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_blockpool_delete(VCOS_BLOCKPOOL_T *pool)
-+{
-+   vcos_generic_blockpool_delete(pool);
-+}
-+
-+VCOS_INLINE_IMPL
-+uint32_t vcos_blockpool_elem_to_handle(void *block)
-+{
-+   return vcos_generic_blockpool_elem_to_handle(block);
-+}
-+
-+VCOS_INLINE_IMPL
-+void *vcos_blockpool_elem_from_handle(VCOS_BLOCKPOOL_T *pool, uint32_t handle)
-+{
-+   return vcos_generic_blockpool_elem_from_handle(pool, handle);
-+}
-+
-+VCOS_INLINE_IMPL
-+uint32_t vcos_blockpool_is_valid_elem(VCOS_BLOCKPOOL_T *pool, const void *block)
-+{
-+   return vcos_generic_blockpool_is_valid_elem(pool, block);
-+}
-+#endif /* VCOS_INLINE_BODIES */
-+
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif /* VCOS_GENERIC_BLOCKPOOL_H */
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_event_flags.c
-@@ -0,0 +1,297 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - event flags implemented via mutexes
-+=============================================================================*/
-+
-+#include "interface/vcos/vcos.h"
-+#include "interface/vcos/generic/vcos_generic_event_flags.h"
-+
-+#include <stddef.h>
-+
-+/** A structure created by a thread that waits on the event flags
-+  * for a particular combination of flags to arrive.
-+  */
-+typedef struct VCOS_EVENT_WAITER_T
-+{
-+   VCOS_UNSIGNED requested_events;  /**< The events wanted */
-+   VCOS_UNSIGNED actual_events;     /**< Actual events found */
-+   VCOS_UNSIGNED op;                /**< The event operation to be used */
-+   VCOS_STATUS_T return_status;     /**< The return status the waiter should pass back */
-+   VCOS_EVENT_FLAGS_T *flags;       /**< Pointer to the original 'flags' structure */
-+   VCOS_THREAD_T *thread;           /**< Thread waiting */
-+   struct VCOS_EVENT_WAITER_T *next;
-+} VCOS_EVENT_WAITER_T;
-+
-+#ifndef NDEBUG
-+static int waiter_list_valid(VCOS_EVENT_FLAGS_T *flags);
-+#endif
-+static void event_flags_timer_expired(void *cxt);
-+
-+VCOS_STATUS_T vcos_generic_event_flags_create(VCOS_EVENT_FLAGS_T *flags, const char *name)
-+{
-+   VCOS_STATUS_T rc;
-+   if ((rc=vcos_mutex_create(&flags->lock, name)) != VCOS_SUCCESS)
-+   {
-+      return rc;
-+   }
-+
-+   flags->events = 0;
-+   flags->waiters.head = flags->waiters.tail = 0;
-+   return rc;
-+}
-+
-+void vcos_generic_event_flags_set(VCOS_EVENT_FLAGS_T *flags,
-+                                  VCOS_UNSIGNED bitmask,
-+                                  VCOS_OPTION op)
-+{
-+   vcos_assert(flags);
-+   vcos_mutex_lock(&flags->lock);
-+   if (op == VCOS_OR)
-+   {
-+      flags->events |= bitmask;
-+   }
-+   else if (op == VCOS_AND)
-+   {
-+      flags->events &= bitmask;
-+   }
-+   else
-+   {
-+      vcos_assert(0);
-+   }
-+
-+   /* Now wake up any threads that have now become signalled. */
-+   if (flags->waiters.head != NULL)
-+   {
-+      VCOS_UNSIGNED consumed_events = 0;
-+      VCOS_EVENT_WAITER_T **pcurrent_waiter = &flags->waiters.head;
-+      VCOS_EVENT_WAITER_T *prev_waiter = NULL;
-+
-+      /* Walk the chain of tasks suspend on this event flag group to determine
-+       * if any of their requests can be satisfied.
-+       */
-+      while ((*pcurrent_waiter) != NULL)
-+      {
-+         VCOS_EVENT_WAITER_T *curr_waiter = *pcurrent_waiter;
-+
-+         /* Determine if this request has been satisfied */
-+
-+         /* First, find the event flags in common. */
-+         VCOS_UNSIGNED waiter_satisfied = flags->events & curr_waiter->requested_events;
-+
-+         /* Second, determine if all the event flags must match */
-+         if (curr_waiter->op & VCOS_AND)
-+         {
-+            /* All requested events must be present */
-+            waiter_satisfied = (waiter_satisfied == curr_waiter->requested_events);
-+         }
-+
-+         /* Wake this one up? */
-+         if (waiter_satisfied)
-+         {
-+
-+            if (curr_waiter->op & VCOS_CONSUME)
-+            {
-+               consumed_events |= curr_waiter->requested_events;
-+            }
-+
-+            /* remove this block from the list, taking care at the end */
-+            *pcurrent_waiter = curr_waiter->next;
-+            if (curr_waiter->next == NULL)
-+               flags->waiters.tail = prev_waiter;
-+
-+            vcos_assert(waiter_list_valid(flags));
-+
-+            curr_waiter->return_status = VCOS_SUCCESS;
-+            curr_waiter->actual_events = flags->events;
-+
-+            _vcos_thread_sem_post(curr_waiter->thread);
-+         }
-+         else
-+         {
-+            /* move to next element in the list */
-+            prev_waiter = *pcurrent_waiter;
-+            pcurrent_waiter = &(curr_waiter->next);
-+         }
-+      }
-+
-+      flags->events &= ~consumed_events;
-+
-+   }
-+
-+   vcos_mutex_unlock(&flags->lock);
-+}
-+
-+void vcos_generic_event_flags_delete(VCOS_EVENT_FLAGS_T *flags)
-+{
-+   vcos_mutex_delete(&flags->lock);
-+}
-+
-+extern VCOS_STATUS_T vcos_generic_event_flags_get(VCOS_EVENT_FLAGS_T *flags,
-+                                                  VCOS_UNSIGNED bitmask,
-+                                                  VCOS_OPTION op,
-+                                                  VCOS_UNSIGNED suspend,
-+                                                  VCOS_UNSIGNED *retrieved_bits)
-+{
-+   VCOS_EVENT_WAITER_T waitreq;
-+   VCOS_STATUS_T rc = VCOS_EAGAIN;
-+   int satisfied = 0;
-+
-+   vcos_assert(flags);
-+
-+   /* default retrieved bits to 0 */
-+   *retrieved_bits = 0;
-+
-+   vcos_mutex_lock(&flags->lock);
-+   switch (op & VCOS_EVENT_FLAG_OP_MASK)
-+   {
-+   case VCOS_AND:
-+      if ((flags->events & bitmask) == bitmask)
-+      {
-+         *retrieved_bits = flags->events;
-+         rc = VCOS_SUCCESS;
-+         satisfied = 1;
-+         if (op & VCOS_CONSUME)
-+            flags->events &= ~bitmask;
-+      }
-+      break;
-+
-+   case VCOS_OR:
-+      if (flags->events & bitmask)
-+      {
-+         *retrieved_bits = flags->events;
-+         rc = VCOS_SUCCESS;
-+         satisfied = 1;
-+         if (op & VCOS_CONSUME)
-+            flags->events &= ~bitmask;
-+      }
-+      break;
-+
-+   default:
-+      vcos_assert(0);
-+      rc = VCOS_EINVAL;
-+      break;
-+   }
-+
-+   if (!satisfied && suspend)
-+   {
-+      /* Have to go to sleep.
-+       *
-+       * Append to tail so we get FIFO ordering.
-+       */
-+      waitreq.requested_events = bitmask;
-+      waitreq.op = op;
-+      waitreq.return_status = VCOS_EAGAIN;
-+      waitreq.flags = flags;
-+      waitreq.actual_events = 0;
-+      waitreq.thread = vcos_thread_current();
-+      waitreq.next = 0;
-+      vcos_assert(waitreq.thread != (VCOS_THREAD_T*)-1);
-+      VCOS_QUEUE_APPEND_TAIL(&flags->waiters, &waitreq);
-+
-+      if (suspend != (VCOS_UNSIGNED)-1)
-+         _vcos_task_timer_set(event_flags_timer_expired, &waitreq, suspend);
-+
-+      vcos_mutex_unlock(&flags->lock);
-+      /* go to sleep and wait to be signalled or timeout */
-+
-+      _vcos_thread_sem_wait();
-+
-+      *retrieved_bits = waitreq.actual_events;
-+      rc = waitreq.return_status;
-+
-+      /* cancel the timer - do not do this while holding the mutex as it
-+       * might be waiting for the timeout function to complete, which will
-+       * try to take the mutex.
-+       */
-+      if (suspend != (VCOS_UNSIGNED)-1)
-+         _vcos_task_timer_cancel();
-+   }
-+   else
-+   {
-+      vcos_mutex_unlock(&flags->lock);
-+   }
-+
-+   return rc;
-+}
-+
-+
-+/** Called when a get call times out. Remove this thread's
-+  * entry from the waiting queue, then resume the thread.
-+  */
-+static void event_flags_timer_expired(void *cxt)
-+{
-+   VCOS_EVENT_WAITER_T *waitreq = (VCOS_EVENT_WAITER_T *)cxt;
-+   VCOS_EVENT_FLAGS_T *flags = waitreq->flags;
-+   VCOS_EVENT_WAITER_T **plist;
-+   VCOS_EVENT_WAITER_T *prev = NULL;
-+   VCOS_THREAD_T *thread = 0;
-+
-+   vcos_assert(flags);
-+
-+   vcos_mutex_lock(&flags->lock);
-+
-+   /* walk the list of waiting threads on this event group, and remove
-+    * the one that has expired.
-+    *
-+    * FIXME: could use doubly-linked list if lots of threads are found
-+    * to be waiting on a single event flag instance.
-+    */
-+   plist = &flags->waiters.head;
-+   while (*plist != NULL)
-+   {
-+      if (*plist == waitreq)
-+      {
-+         int at_end;
-+         /* found it */
-+         thread = (*plist)->thread;
-+         at_end = ((*plist)->next == NULL);
-+
-+         /* link past */
-+         *plist = (*plist)->next;
-+         if (at_end)
-+            flags->waiters.tail = prev;
-+
-+         break;
-+      }
-+      prev = *plist;
-+      plist = &(*plist)->next;
-+   }
-+   vcos_assert(waiter_list_valid(flags));
-+
-+   vcos_mutex_unlock(&flags->lock);
-+
-+   if (thread)
-+   {
-+      _vcos_thread_sem_post(thread);
-+   }
-+}
-+
-+#ifndef NDEBUG
-+
-+static int waiter_list_valid(VCOS_EVENT_FLAGS_T *flags)
-+{
-+   int valid;
-+   /* Either both head and tail are NULL, or neither are NULL */
-+   if (flags->waiters.head == NULL)
-+   {
-+      valid = (flags->waiters.tail == NULL);
-+   }
-+   else
-+   {
-+      valid = (flags->waiters.tail != NULL);
-+   }
-+
-+   /* If head and tail point at the same non-NULL element, then there
-+    * is only one element in the list.
-+    */
-+   if (flags->waiters.head && (flags->waiters.head == flags->waiters.tail))
-+   {
-+      valid = (flags->waiters.head->next == NULL);
-+   }
-+   return valid;
-+}
-+
-+#endif
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_event_flags.h
-@@ -0,0 +1,104 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - event flags implemented via a semaphore
-+=============================================================================*/
-+
-+#ifndef VCOS_GENERIC_EVENT_FLAGS_H
-+#define VCOS_GENERIC_EVENT_FLAGS_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+
-+/**
-+  * \file
-+  *
-+  * This provides event flags (as per Nucleus Event Groups) based on a
-+  * mutex, a semaphore (per waiting thread) and a timer (per waiting
-+  * thread).
-+  * 
-+  * The data structure is a 32 bit unsigned int (the current set of
-+  * flags) and a linked list of clients waiting to be 'satisfied'.
-+  *
-+  * The mutex merely locks access to the data structure. If a client
-+  * calls vcos_event_flags_get() and the requested bits are not already
-+  * present, it then sleeps on its per-thread semaphore after adding
-+  * this semaphore to the queue waiting. It also sets up a timer.
-+  *
-+  * The per-thread semaphore and timer are actually stored in the
-+  * thread context (joinable thread). In future it may become necessary
-+  * to support non-VCOS threads by using thread local storage to
-+  * create these objects and associate them with the thread.
-+  */
-+
-+struct VCOS_EVENT_WAITER_T;
-+
-+typedef struct VCOS_EVENT_FLAGS_T
-+{
-+   VCOS_UNSIGNED events;      /**< Events currently set */
-+   VCOS_MUTEX_T lock;         /**< Serialize access */
-+   struct
-+   {
-+      struct VCOS_EVENT_WAITER_T *head;   /**< List of threads waiting */
-+      struct VCOS_EVENT_WAITER_T *tail;   /**< List of threads waiting */
-+   } waiters;
-+} VCOS_EVENT_FLAGS_T;
-+
-+#define VCOS_OR      1
-+#define VCOS_AND     2
-+#define VCOS_CONSUME 4
-+#define VCOS_OR_CONSUME (VCOS_OR | VCOS_CONSUME)
-+#define VCOS_AND_CONSUME (VCOS_AND | VCOS_CONSUME)
-+#define VCOS_EVENT_FLAG_OP_MASK (VCOS_OR|VCOS_AND)
-+
-+VCOSPRE_  VCOS_STATUS_T VCOSPOST_ vcos_generic_event_flags_create(VCOS_EVENT_FLAGS_T *flags, const char *name);
-+VCOSPRE_  void VCOSPOST_ vcos_generic_event_flags_set(VCOS_EVENT_FLAGS_T *flags,
-+                                                      VCOS_UNSIGNED events,
-+                                                      VCOS_OPTION op);
-+VCOSPRE_  void VCOSPOST_ vcos_generic_event_flags_delete(VCOS_EVENT_FLAGS_T *);
-+VCOSPRE_  VCOS_STATUS_T VCOSPOST_ vcos_generic_event_flags_get(VCOS_EVENT_FLAGS_T *flags,
-+                                                               VCOS_UNSIGNED requested_events,
-+                                                               VCOS_OPTION op,
-+                                                               VCOS_UNSIGNED suspend,
-+                                                               VCOS_UNSIGNED *retrieved_events);
-+
-+#ifdef VCOS_INLINE_BODIES
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_event_flags_create(VCOS_EVENT_FLAGS_T *flags, const char *name) {
-+   return vcos_generic_event_flags_create(flags, name);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_event_flags_set(VCOS_EVENT_FLAGS_T *flags,
-+                          VCOS_UNSIGNED events,
-+                          VCOS_OPTION op) {
-+   vcos_generic_event_flags_set(flags, events, op);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_event_flags_delete(VCOS_EVENT_FLAGS_T *f) {
-+   vcos_generic_event_flags_delete(f);
-+}
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_event_flags_get(VCOS_EVENT_FLAGS_T *flags,
-+                                   VCOS_UNSIGNED requested_events,
-+                                   VCOS_OPTION op,
-+                                   VCOS_UNSIGNED suspend,
-+                                   VCOS_UNSIGNED *retrieved_events) {
-+   return vcos_generic_event_flags_get(flags, requested_events, op, suspend, retrieved_events);
-+}
-+
-+#endif /* VCOS_INLINE_BODIES */
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_named_sem.h
-@@ -0,0 +1,81 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - named semaphores
-+=============================================================================*/
-+
-+#ifndef VCOS_GENERIC_NAMED_SEM_H
-+#define VCOS_GENERIC_NAMED_SEM_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+
-+/**
-+ * \file
-+ *
-+ * Generic support for named semaphores, using regular ones. This is only
-+ * suitable for emulating them on an embedded MMUless system, since there is
-+ * no support for opening semaphores across process boundaries.
-+ *
-+ */
-+
-+#define VCOS_NAMED_SEMAPHORE_NAMELEN   64
-+
-+/* In theory we could use the name facility provided within Nucleus. However, this
-+ * is hard to do as semaphores are constantly being created and destroyed; we
-+ * would need to stop everything while allocating the memory for the semaphore
-+ * list and then walking it. So keep our own list.
-+ */
-+typedef struct VCOS_NAMED_SEMAPHORE_T
-+{
-+   struct VCOS_NAMED_SEMAPHORE_IMPL_T *actual; /**< There are 'n' named semaphores per 1 actual semaphore  */
-+   VCOS_SEMAPHORE_T *sem;                      /**< Pointer to actual underlying semaphore */
-+} VCOS_NAMED_SEMAPHORE_T;
-+
-+VCOSPRE_ VCOS_STATUS_T VCOSPOST_
-+vcos_generic_named_semaphore_create(VCOS_NAMED_SEMAPHORE_T *sem, const char *name, VCOS_UNSIGNED count);
-+
-+VCOSPRE_ void VCOSPOST_ vcos_named_semaphore_delete(VCOS_NAMED_SEMAPHORE_T *sem);
-+
-+VCOSPRE_ VCOS_STATUS_T VCOSPOST_ _vcos_named_semaphore_init(void);
-+VCOSPRE_ void VCOSPOST_ _vcos_named_semaphore_deinit(void);
-+
-+#if defined(VCOS_INLINE_BODIES)
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_named_semaphore_create(VCOS_NAMED_SEMAPHORE_T *sem, const char *name, VCOS_UNSIGNED count) {
-+   return vcos_generic_named_semaphore_create(sem, name, count);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_named_semaphore_wait(VCOS_NAMED_SEMAPHORE_T *sem) {
-+   vcos_semaphore_wait(sem->sem);
-+}
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_named_semaphore_trywait(VCOS_NAMED_SEMAPHORE_T *sem) {
-+   return vcos_semaphore_trywait(sem->sem);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_named_semaphore_post(VCOS_NAMED_SEMAPHORE_T *sem) {
-+   vcos_semaphore_post(sem->sem);
-+}
-+
-+
-+#endif
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif
-+
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_quickslow_mutex.h
-@@ -0,0 +1,75 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - reentrant mutexes created from regular ones.
-+=============================================================================*/
-+
-+#ifndef VCOS_GENERIC_QUICKSLOW_MUTEX_H
-+#define VCOS_GENERIC_QUICKSLOW_MUTEX_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+
-+/**
-+ * \file
-+ *
-+ * Quickslow Mutexes implemented as regular ones (i.e. quick and slow modes are the same).
-+ *
-+ */
-+
-+typedef VCOS_MUTEX_T VCOS_QUICKSLOW_MUTEX_T;
-+
-+#if defined(VCOS_INLINE_BODIES)
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_quickslow_mutex_create(VCOS_QUICKSLOW_MUTEX_T *m, const char *name)
-+{
-+   return vcos_mutex_create(m, name);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_quickslow_mutex_delete(VCOS_QUICKSLOW_MUTEX_T *m)
-+{
-+   vcos_mutex_delete(m);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_quickslow_mutex_lock(VCOS_QUICKSLOW_MUTEX_T *m)
-+{
-+   while (vcos_mutex_lock(m) == VCOS_EAGAIN);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_quickslow_mutex_unlock(VCOS_QUICKSLOW_MUTEX_T *m)
-+{
-+   vcos_mutex_unlock(m);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_quickslow_mutex_lock_quick(VCOS_QUICKSLOW_MUTEX_T *m)
-+{
-+   while (vcos_mutex_lock(m) == VCOS_EAGAIN);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_quickslow_mutex_unlock_quick(VCOS_QUICKSLOW_MUTEX_T *m)
-+{
-+   vcos_mutex_unlock(m);
-+}
-+
-+#endif
-+
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif
-+
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_reentrant_mtx.h
-@@ -0,0 +1,75 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - reentrant mutexes created from regular ones.
-+=============================================================================*/
-+
-+#ifndef VCOS_GENERIC_REENTRANT_MUTEX_H
-+#define VCOS_GENERIC_REENTRANT_MUTEX_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+
-+/**
-+ * \file
-+ *
-+ * Reentrant Mutexes from regular ones.
-+ *
-+ */
-+
-+typedef struct VCOS_REENTRANT_MUTEX_T
-+{
-+   VCOS_MUTEX_T mutex;
-+   VCOS_THREAD_T *owner;
-+   unsigned count;
-+} VCOS_REENTRANT_MUTEX_T;
-+
-+/* Extern definitions of functions that do the actual work */
-+
-+VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_generic_reentrant_mutex_create(VCOS_REENTRANT_MUTEX_T *m, const char *name);
-+
-+VCOSPRE_ void VCOSPOST_ vcos_generic_reentrant_mutex_delete(VCOS_REENTRANT_MUTEX_T *m);
-+
-+VCOSPRE_ void VCOSPOST_ vcos_generic_reentrant_mutex_lock(VCOS_REENTRANT_MUTEX_T *m);
-+
-+VCOSPRE_ void VCOSPOST_ vcos_generic_reentrant_mutex_unlock(VCOS_REENTRANT_MUTEX_T *m);
-+
-+/* Inline forwarding functions */
-+
-+#if defined(VCOS_INLINE_BODIES)
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_reentrant_mutex_create(VCOS_REENTRANT_MUTEX_T *m, const char *name) {
-+   return vcos_generic_reentrant_mutex_create(m,name);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_reentrant_mutex_delete(VCOS_REENTRANT_MUTEX_T *m) {
-+   vcos_generic_reentrant_mutex_delete(m);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_reentrant_mutex_lock(VCOS_REENTRANT_MUTEX_T *m) {
-+   vcos_generic_reentrant_mutex_lock(m);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_reentrant_mutex_unlock(VCOS_REENTRANT_MUTEX_T *m) {
-+   vcos_generic_reentrant_mutex_unlock(m);
-+}
-+#endif
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif
-+
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_tls.h
-@@ -0,0 +1,144 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - generic thread local storage
-+=============================================================================*/
-+
-+#ifndef VCOS_GENERIC_TLS_H
-+#define VCOS_GENERIC_TLS_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+
-+/**
-+  * \file
-+  *
-+  * Do an emulation of Thread Local Storage. The platform needs to
-+  * provide a way to set and get a per-thread pointer which is
-+  * where the TLS data itself is stored.
-+  *
-+  *
-+  * Each thread that wants to join in this scheme needs to call
-+  * vcos_tls_thread_register().
-+  *
-+  * The platform needs to support the macros/functions
-+  * _vcos_tls_thread_ptr_set() and _vcos_tls_thread_ptr_get().
-+  */
-+
-+#ifndef VCOS_WANT_TLS_EMULATION
-+#error Should not be included unless TLS emulation is defined
-+#endif
-+
-+/** Number of slots to reserve per thread. This results in an overhead
-+  * of this many words per thread.
-+  */
-+#define VCOS_TLS_MAX_SLOTS 4
-+
-+/** TLS key. Allocating one of these reserves the client one of the 
-+  * available slots.
-+  */
-+typedef VCOS_UNSIGNED VCOS_TLS_KEY_T;
-+
-+/** TLS per-thread structure. Each thread gets one of these
-+  * if TLS emulation (rather than native TLS support) is
-+  * being used.
-+  */
-+typedef struct VCOS_TLS_THREAD_T
-+{
-+   void *slots[VCOS_TLS_MAX_SLOTS];
-+} VCOS_TLS_THREAD_T;
-+
-+/*
-+ * Internal APIs 
-+ */
-+
-+/** Register this thread's TLS storage area. */
-+VCOSPRE_ void VCOSPOST_ vcos_tls_thread_register(VCOS_TLS_THREAD_T *);
-+
-+/** Create a new TLS key */
-+VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_generic_tls_create(VCOS_TLS_KEY_T *key);
-+
-+/** Delete a TLS key */
-+VCOSPRE_ void VCOSPOST_ vcos_generic_tls_delete(VCOS_TLS_KEY_T tls);
-+
-+/** Initialise the TLS library */
-+VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_tls_init(void);
-+
-+/** Deinitialise the TLS library */
-+VCOSPRE_ void VCOSPOST_ vcos_tls_deinit(void);
-+
-+#if defined(VCOS_INLINE_BODIES)
-+
-+#undef VCOS_ASSERT_LOGGING_DISABLE
-+#define VCOS_ASSERT_LOGGING_DISABLE 1
-+
-+/*
-+ * Implementations of public API functions
-+ */
-+
-+/** Set the given value. Since everything is per-thread, there is no need
-+  * for any locking.
-+  */
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_tls_set(VCOS_TLS_KEY_T tls, void *v) {
-+   VCOS_TLS_THREAD_T *tlsdata = _vcos_tls_thread_ptr_get();
-+   vcos_assert(tlsdata); /* Fires if this thread has not been registered */
-+   if (tls<VCOS_TLS_MAX_SLOTS)
-+   {
-+      tlsdata->slots[tls] = v;
-+      return VCOS_SUCCESS;
-+   }
-+   else
-+   {
-+      vcos_assert(0);
-+      return VCOS_EINVAL;
-+   }
-+}
-+
-+/** Get the given value. No locking required.
-+  */
-+VCOS_INLINE_IMPL
-+void *vcos_tls_get(VCOS_TLS_KEY_T tls) {
-+   VCOS_TLS_THREAD_T *tlsdata = _vcos_tls_thread_ptr_get();
-+   vcos_assert(tlsdata); /* Fires if this thread has not been registered */
-+   if (tls<VCOS_TLS_MAX_SLOTS)
-+   {
-+      return tlsdata->slots[tls];
-+   }
-+   else
-+   {
-+      vcos_assert(0);
-+      return NULL;
-+   }
-+}
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_tls_create(VCOS_TLS_KEY_T *key) {
-+   return vcos_generic_tls_create(key);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_tls_delete(VCOS_TLS_KEY_T tls) {
-+   vcos_generic_tls_delete(tls);
-+}
-+
-+#undef VCOS_ASSERT_LOGGING_DISABLE
-+#define VCOS_ASSERT_LOGGING_DISABLE 0
-+
-+#endif /* VCOS_INLINE_BODIES */
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif
-+
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_joinable_thread_from_plain.h
-@@ -0,0 +1,202 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Module   :  vcos
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - implementation: joinable thread from plain
-+=============================================================================*/
-+
-+/** \file
-+  *
-+  * Header file for platforms creating the joinable thread from a lowlevel
-+  * thread.
-+  *
-+  * In addition to the actual thread, the following are also created:
-+  *
-+  * - a semaphore to wait on when joining the thread
-+  * - a semaphore to support counted suspend/resume (used by event group)
-+  * - a per-thread timer (used by event group, but could be removed)
-+  */
-+
-+#ifndef VCOS_JOINABLE_THREAD_FROM_PLAIN_H
-+#define VCOS_JOINABLE_THREAD_FROM_PLAIN_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_semaphore.h"
-+#include "interface/vcos/vcos_lowlevel_thread.h"
-+#include "interface/vcos/vcos_timer.h"
-+
-+#ifdef VCOS_WANT_TLS_EMULATION
-+#include "interface/vcos/generic/vcos_generic_tls.h"
-+#endif
-+
-+#define VCOS_THREAD_MAGIC 0x56436a74
-+
-+#define VCOS_THREAD_VALID(t) (t->magic == VCOS_THREAD_MAGIC)
-+#define VCOS_HAVE_THREAD_AT_EXIT        1
-+
-+/** Thread attribute structure. Clients should not manipulate this directly, but
-+  * should instead use the provided functions.
-+  */
-+typedef struct VCOS_THREAD_ATTR_T
-+{
-+   void *ta_stackaddr;
-+   VCOS_UNSIGNED ta_stacksz;
-+   VCOS_UNSIGNED ta_priority;
-+   VCOS_UNSIGNED ta_affinity;
-+   VCOS_UNSIGNED ta_timeslice;
-+   VCOS_UNSIGNED legacy;
-+   VCOS_UNSIGNED ta_autostart;
-+} VCOS_THREAD_ATTR_T;
-+
-+/** Each thread gets a timer, which is for internal VCOS use.
-+  */
-+typedef struct _VCOS_THREAD_TIMER_T
-+{
-+   VCOS_TIMER_T timer;
-+   void (*pfn)(void *);
-+   void *cxt;
-+} _VCOS_THREAD_TIMER_T;
-+
-+typedef void (*VCOS_THREAD_EXIT_HANDLER_T)(void *);
-+/** Called at thread exit.
-+  */
-+typedef struct VCOS_THREAD_EXIT_T
-+{
-+   VCOS_THREAD_EXIT_HANDLER_T pfn;
-+   void *cxt;
-+} VCOS_THREAD_EXIT_T;
-+#define VCOS_MAX_EXIT_HANDLERS  8
-+
-+/* The name field isn't used for anything, so we can just copy the
-+ * the pointer. Nucleus makes its own copy.
-+ */
-+typedef const char *          VCOS_LLTHREAD_T_NAME;
-+#define _VCOS_LLTHREAD_NAME(dst,src) (dst)=(src)
-+
-+/*
-+ * Simulated TLS support
-+ */
-+
-+
-+/** Thread structure.
-+  *
-+  * \warning Do not access the members of this structure directly!
-+  */
-+typedef struct VCOS_THREAD_T
-+{
-+   VCOS_LLTHREAD_T  thread;      /**< The underlying thread */
-+   char name[16];                /**< The name */
-+   unsigned int     magic;       /**< For debug */
-+   void            *exit_data;   /**< Exit data passed out in vcos_joinable_thread_exit() */
-+   void            *stack;       /**< Stack, if not supplied by caller */
-+   VCOS_SEMAPHORE_T wait;        /**< Semaphore to wait on at join */
-+   VCOS_SEMAPHORE_T suspend;     /**< Semaphore to wait on for counted suspend */
-+   int16_t          joined;      /**< Joined yet? For debug. */
-+   VCOS_UNSIGNED    legacy;      /**< Use (argc,argv) for entry point arguments */
-+   void *(*entry)(void*);        /**< Entry point */
-+   void             *arg;        /**< Argument passed to entry point */
-+   void *(*term)(void*);         /**< Termination function, used by reaper */
-+   void             *term_arg;   /**< Argument passed to termination function */
-+   _VCOS_THREAD_TIMER_T _timer;  /**< Internal timer, mainly for event groups */
-+#ifdef VCOS_WANT_TLS_EMULATION
-+   VCOS_TLS_THREAD_T   _tls;     /**< TLS data when native TLS not available, or NULL */
-+#endif
-+   /** Array of functions to call at thread exit */
-+   VCOS_THREAD_EXIT_T at_exit[VCOS_MAX_EXIT_HANDLERS];
-+
-+   struct VCOS_THREAD_T *next;   /**< For linked lists of threads */
-+} VCOS_THREAD_T;
-+
-+#if defined(VCOS_INLINE_BODIES)
-+
-+VCOS_INLINE_IMPL
-+void vcos_thread_attr_setstack(VCOS_THREAD_ATTR_T *attrs, void *addr, VCOS_UNSIGNED stacksz) {
-+   attrs->ta_stackaddr = addr;
-+   attrs->ta_stacksz = stacksz;
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_thread_attr_setstacksize(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED stacksz) {
-+   attrs->ta_stacksz = stacksz;
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_thread_attr_setpriority(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED pri) {
-+   attrs->ta_priority = pri;
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_thread_attr_setaffinity(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED affinity) {
-+   attrs->ta_affinity = affinity;
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_thread_attr_settimeslice(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED ts) {
-+   attrs->ta_timeslice = ts;
-+}
-+
-+VCOS_INLINE_IMPL
-+void _vcos_thread_attr_setlegacyapi(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED legacy) {
-+   attrs->legacy = legacy;
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_thread_attr_setautostart(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED autostart) {
-+   attrs->ta_autostart = autostart;
-+}
-+
-+VCOS_INLINE_IMPL
-+VCOS_THREAD_T *vcos_thread_current(void) {
-+   VCOS_THREAD_T *ret =  (VCOS_THREAD_T*)vcos_llthread_current();
-+   /*If we're called from a non-vcos thread, this assert will fail.
-+    *XXX FIXME why is this commented out?
-+    *vcos_assert(ret->magic == VCOS_THREAD_MAGIC);
-+    */
-+   return ret;
-+}
-+
-+VCOS_INLINE_IMPL
-+int vcos_thread_running(VCOS_THREAD_T *thread) {
-+   return vcos_llthread_running(&thread->thread);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_thread_resume(VCOS_THREAD_T *thread) {
-+   vcos_llthread_resume(&thread->thread);
-+}
-+
-+#endif /* VCOS_INLINE_BODIES */
-+
-+/**
-+  * \brief Create a VCOS_THREAD_T for the current thread. This is so we can have
-+  * VCOS_THREAD_Ts even for threads not originally created by VCOS (eg the
-+  * thread that calls vcos_init)
-+  */
-+extern VCOS_STATUS_T _vcos_thread_create_attach(VCOS_THREAD_T *thread,
-+                                                const char *name);
-+
-+/**
-+  * \brief Deletes the VCOS_THREAD_T, but does not wait for the underlying
-+  * thread to exit. This will cleanup everything created by
-+  * _vcos_thread_create_attach
-+  */
-+extern void _vcos_thread_delete(VCOS_THREAD_T *thread);
-+
-+/** Register a function to be called when the current thread exits.
-+  */
-+extern VCOS_STATUS_T vcos_thread_at_exit(void (*pfn)(void*), void *cxt);
-+
-+/** Deregister a previously registered at-exit function.
-+  */
-+extern void vcos_thread_deregister_at_exit(void (*pfn)(void*), void *cxt);
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif /* VCOS_JOINABLE_THREAD_FROM_PLAIN_H */
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_latch_from_sem.h
-@@ -0,0 +1,48 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  vcos
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - Construct a latch from a semaphore
-+=============================================================================*/
-+
-+/** FIXME: rename to vcos_mutex_from_sem.c
-+  */
-+
-+typedef struct VCOS_MUTEX_T {
-+   VCOS_SEMAPHORE_T sem;
-+   struct VCOS_THREAD_T *owner;
-+} VCOS_MUTEX_T;
-+
-+extern VCOS_STATUS_T vcos_generic_mutex_create(VCOS_MUTEX_T *latch, const char *name);
-+extern void vcos_generic_mutex_delete(VCOS_MUTEX_T *latch);
-+extern VCOS_STATUS_T vcos_generic_mutex_lock(VCOS_MUTEX_T *latch);
-+extern void vcos_generic_mutex_unlock(VCOS_MUTEX_T *latch);
-+
-+#if defined(VCOS_INLINE_BODIES)
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_mutex_create(VCOS_MUTEX_T *latch, const char *name) {
-+   return vcos_generic_mutex_create(latch,name);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_mutex_delete(VCOS_MUTEX_T *latch) {
-+   vcos_generic_mutex_delete(latch);
-+}
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_mutex_lock(VCOS_MUTEX_T *latch) {
-+   return vcos_generic_mutex_lock(latch);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_mutex_unlock(VCOS_MUTEX_T *latch) {
-+   vcos_generic_mutex_unlock(latch);
-+}
-+
-+#endif /* VCOS_INLINE_BODIES */
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_logcat.c
-@@ -0,0 +1,549 @@
-+/*=============================================================================
-+Copyright (c) 2010 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  vcos
-+
-+FILE DESCRIPTION
-+Categorized logging for VCOS - a generic implementation.
-+=============================================================================*/
-+
-+#include "interface/vcos/vcos.h"
-+#include "interface/vcos/vcos_ctype.h"
-+#include "interface/vcos/vcos_string.h"
-+
-+static VCOS_MUTEX_T lock;
-+static int warned_loglevel;             /* only warn about invalid log level once */
-+static VCOS_VLOG_IMPL_FUNC_T vcos_vlog_impl_func = vcos_vlog_default_impl;
-+
-+#define  VCOS_LOG_CATEGORY (&dflt_log_category)
-+static VCOS_LOG_CAT_T dflt_log_category;
-+VCOS_LOG_CAT_T *vcos_logging_categories = NULL;
-+static int inited;
-+
-+#if VCOS_HAVE_CMD
-+
-+/*
-+ * For kernel or videocore purposes, we generally want the log command. For 
-+ * user-space apps, they might want to provide their own log command, so we 
-+ * don't include the built in on. 
-+ *  
-+ * So pthreads/vcos_platform.h defines VCOS_WANT_LOG_CMD to be 0. It is 
-+ * undefined elsewhere. 
-+ */
-+
-+#  if !defined( VCOS_WANT_LOG_CMD )
-+#     define  VCOS_WANT_LOG_CMD 1
-+#  endif
-+#else
-+#  define VCOS_WANT_LOG_CMD   0
-+#endif
-+
-+#if VCOS_WANT_LOG_CMD
-+
-+/*****************************************************************************
-+*
-+*   Does a vcos_assert(0), which is useful to test logging.
-+*
-+*****************************************************************************/
-+
-+VCOS_STATUS_T vcos_log_assert_cmd( VCOS_CMD_PARAM_T *param )
-+{
-+   (void)param;
-+
-+#if defined( NDEBUG ) && !defined( VCOS_RELEASE_ASSERTS )
-+   vcos_log_error( "vcos_asserts have been compiled out" );
-+   vcos_cmd_printf( param, "vcos_asserts have been compiled out - did a vcos_log_error instead\n" );
-+#else
-+   vcos_assert(0);
-+   vcos_cmd_printf( param, "Executed vcos_assert(0)\n" );
-+#endif
-+
-+   return VCOS_SUCCESS;
-+}
-+
-+/*****************************************************************************
-+*
-+*   Sets a vcos logging level
-+*
-+*****************************************************************************/
-+
-+VCOS_STATUS_T vcos_log_set_cmd( VCOS_CMD_PARAM_T *param )
-+{
-+   VCOS_LOG_CAT_T   *cat;
-+   char             *name;
-+   char             *levelStr;
-+   VCOS_LOG_LEVEL_T  level;
-+   VCOS_STATUS_T     status;
-+
-+   if ( param->argc != 3 )
-+   {
-+      vcos_cmd_usage( param );
-+      return VCOS_EINVAL;
-+   }
-+
-+   name = param->argv[1];
-+   levelStr = param->argv[2];
-+
-+   if ( vcos_string_to_log_level( levelStr, &level ) != VCOS_SUCCESS )
-+   {
-+      vcos_cmd_printf( param, "Unrecognized logging level: '%s'\n", levelStr );
-+      return VCOS_EINVAL;
-+   }
-+
-+   vcos_mutex_lock(&lock);
-+
-+   status = VCOS_SUCCESS;
-+   for ( cat = vcos_logging_categories; cat != NULL; cat = cat->next )
-+   {
-+      if ( vcos_strcmp( name, cat->name ) == 0 )
-+      {
-+         cat->level = level;
-+         vcos_cmd_printf( param, "Category %s level set to %s\n", name, levelStr );
-+         break;
-+      }
-+   }
-+   if ( cat == NULL )
-+   {
-+      vcos_cmd_printf( param, "Unrecognized category: '%s'\n", name );
-+      status = VCOS_ENOENT;
-+   }
-+
-+   vcos_mutex_unlock(&lock);
-+
-+   return status;
-+}
-+
-+/*****************************************************************************
-+*
-+*   Prints out the current settings for a given category (or all cvategories)
-+*
-+*****************************************************************************/
-+
-+VCOS_STATUS_T vcos_log_status_cmd( VCOS_CMD_PARAM_T *param )
-+{
-+   VCOS_LOG_CAT_T   *cat;
-+   VCOS_STATUS_T     status;
-+
-+   vcos_mutex_lock(&lock);
-+
-+   if ( param->argc == 1)
-+   {
-+      int   nw;
-+      int   nameWidth = 0;
-+
-+      /* Print information about all of the categories. */
-+
-+      for ( cat = vcos_logging_categories; cat != NULL; cat = cat->next )
-+      {
-+         nw = (int)strlen( cat->name );
-+
-+         if ( nw > nameWidth )
-+         {
-+            nameWidth = nw;
-+         }
-+      }
-+
-+      for ( cat = vcos_logging_categories; cat != NULL; cat = cat->next )
-+      {
-+         vcos_cmd_printf( param, "%-*s - %s\n", nameWidth, cat->name, vcos_log_level_to_string( cat->level ));
-+      }
-+   }
-+   else
-+   {
-+      /* Print information about a particular category */
-+
-+      for ( cat = vcos_logging_categories; cat != NULL; cat = cat->next )
-+      {
-+         if ( vcos_strcmp( cat->name, param->argv[1] ) == 0 )
-+         {
-+            vcos_cmd_printf( param, "%s - %s\n", cat->name, vcos_log_level_to_string( cat->level ));
-+            break;
-+         }
-+      }
-+      if ( cat == NULL )
-+      {
-+         vcos_cmd_printf( param, "Unrecognized logging category: '%s'\n", param->argv[1] );
-+         status = VCOS_ENOENT;
-+         goto out;
-+      }
-+   }
-+
-+   status = VCOS_SUCCESS;
-+out:
-+   vcos_mutex_unlock(&lock);
-+
-+   return status;
-+}
-+
-+/*****************************************************************************
-+*
-+*   Prints out the current settings for a given category (or all cvategories)
-+*
-+*****************************************************************************/
-+
-+VCOS_STATUS_T vcos_log_test_cmd( VCOS_CMD_PARAM_T *param )
-+{
-+   if ( param->argc == 1 )
-+   {
-+      static   int seq_num = 100;
-+
-+      /* No additional arguments - generate a message with an incrementing number */
-+
-+      vcos_log_error( "Test message %d", seq_num );
-+
-+      seq_num++;
-+      vcos_cmd_printf( param, "Logged 'Test message %d'\n", seq_num );
-+   }
-+   else
-+   {
-+      int   arg_idx;
-+
-+      /* Arguments supplied - log these */
-+
-+      for ( arg_idx = 0; arg_idx < param->argc; arg_idx++ )
-+      {
-+         vcos_log_error( "argv[%d] = '%s'", arg_idx, param->argv[arg_idx] );
-+      }
-+      vcos_cmd_printf( param, "Logged %d line(s) of test data\n", param->argc );
-+   }
-+   return VCOS_SUCCESS;
-+}
-+
-+/*****************************************************************************
-+*
-+*   Internal commands
-+*
-+*****************************************************************************/
-+
-+static VCOS_CMD_T log_cmd_entry[] =
-+{
-+    { "assert",   "",                  vcos_log_assert_cmd, NULL,    "Does a vcos_assert(0) to test logging" },
-+    { "set",      "category level",    vcos_log_set_cmd,    NULL,    "Sets the vcos logging level for a category" },
-+    { "status",   "[category]",        vcos_log_status_cmd, NULL,    "Prints the vcos log status for a (or all) categories" },
-+    { "test",     "[arbitrary text]",  vcos_log_test_cmd,   NULL,    "Does a vcos_log to test logging" },
-+
-+    { NULL,       NULL,                NULL,                NULL,    NULL }
-+};
-+
-+static VCOS_CMD_T cmd_log =
-+    { "log",        "command [args]",  NULL,    log_cmd_entry, "Commands related to vcos logging" };
-+
-+#endif
-+
-+void vcos_logging_init(void)
-+{
-+   if (inited)
-+   {
-+      /* FIXME: should print a warning or something here */
-+      return;
-+   }
-+   vcos_mutex_create(&lock, "vcos_log");
-+
-+   vcos_log_platform_init();
-+
-+   vcos_log_register("default", &dflt_log_category);
-+
-+#if VCOS_WANT_LOG_CMD
-+   vcos_cmd_register( &cmd_log );
-+#endif
-+
-+   vcos_assert(!inited);
-+   inited = 1;
-+}
-+
-+/** Read an alphanumeric token, returning True if we succeeded.
-+  */
-+
-+static int read_tok(char *tok, size_t toklen, const char **pstr, char sep)
-+{
-+   const char *str = *pstr;
-+   size_t n = 0;
-+   char ch;
-+
-+   /* skip past any whitespace */
-+   while (str[0] && isspace((int)(str[0])))
-+      str++;
-+
-+   while ((ch = *str) != '\0' &&
-+          ch != sep &&
-+          (isalnum((int)ch) || (ch == '_')) &&
-+          n != toklen-1)
-+   {
-+      tok[n++] = ch;
-+      str++;
-+   }
-+
-+   /* did it work out? */
-+   if (ch == '\0' || ch == sep)
-+   {
-+      if (ch) str++; /* move to next token if not at end */
-+      /* yes */
-+      tok[n] = '\0';
-+      *pstr = str;
-+      return 1;
-+   }
-+   else
-+   {
-+      /* no */
-+      return 0;
-+   }
-+}
-+
-+const char *vcos_log_level_to_string( VCOS_LOG_LEVEL_T level )
-+{
-+   switch (level)
-+   {
-+      case VCOS_LOG_UNINITIALIZED:  return "uninit";
-+      case VCOS_LOG_NEVER:          return "never";
-+      case VCOS_LOG_ERROR:          return "error";
-+      case VCOS_LOG_WARN:           return "warn";
-+      case VCOS_LOG_INFO:           return "info";
-+      case VCOS_LOG_TRACE:          return "trace";
-+   }
-+   return "???";
-+}
-+
-+VCOS_STATUS_T vcos_string_to_log_level( const char *str, VCOS_LOG_LEVEL_T *level )
-+{
-+   if (strcmp(str,"error") == 0)
-+      *level = VCOS_LOG_ERROR;
-+   else if (strcmp(str,"never") == 0)
-+      *level = VCOS_LOG_NEVER;
-+   else if (strcmp(str,"warn") == 0)
-+      *level = VCOS_LOG_WARN;
-+   else if (strcmp(str,"warning") == 0)
-+      *level = VCOS_LOG_WARN;
-+   else if (strcmp(str,"info") == 0)
-+      *level = VCOS_LOG_INFO;
-+   else if (strcmp(str,"trace") == 0)
-+      *level = VCOS_LOG_TRACE;
-+   else
-+      return VCOS_EINVAL;
-+
-+   return VCOS_SUCCESS;
-+}
-+
-+static int read_level(VCOS_LOG_LEVEL_T *level, const char **pstr, char sep)
-+{
-+   char buf[16];
-+   int ret = 1;
-+   if (read_tok(buf,sizeof(buf),pstr,sep))
-+   {
-+      if (vcos_string_to_log_level(buf,level) != VCOS_SUCCESS)
-+      {
-+         vcos_log("Invalid trace level '%s'\n", buf);
-+         ret = 0;
-+      }
-+   }
-+   else
-+   {
-+      ret = 0;
-+   }
-+   return ret;
-+}
-+
-+void vcos_log_register(const char *name, VCOS_LOG_CAT_T *category)
-+{
-+   const char *env;
-+   VCOS_LOG_CAT_T *i;
-+
-+   category->name  = name;
-+   if ( category->level == VCOS_LOG_UNINITIALIZED )
-+   {
-+      category->level = VCOS_LOG_ERROR;
-+   }
-+   category->flags.want_prefix = (category != &dflt_log_category );
-+
-+   vcos_mutex_lock(&lock);
-+
-+   /* is it already registered? */
-+   for (i = vcos_logging_categories; i ; i = i->next )
-+   {
-+      if (i == category)
-+      {
-+         i->refcount++;
-+         break;
-+      }
-+   }
-+
-+   if (!i)
-+   {
-+      /* not yet registered */
-+      category->next = vcos_logging_categories;
-+      vcos_logging_categories = category;
-+      category->refcount++;
-+
-+      vcos_log_platform_register(category);
-+   }
-+
-+   vcos_mutex_unlock(&lock);
-+
-+   /* Check to see if this log level has been enabled. Look for
-+    * (<category:level>,)*
-+    *
-+    * VC_LOGLEVEL=ilcs:info,vchiq:warn
-+    */
-+
-+   env = _VCOS_LOG_LEVEL();
-+   if (env)
-+   {
-+      do
-+      {
-+         char env_name[64];
-+         VCOS_LOG_LEVEL_T level;
-+         if (read_tok(env_name, sizeof(env_name), &env, ':') &&
-+             read_level(&level, &env, ','))
-+         {
-+            if (strcmp(env_name, name) == 0)
-+            {
-+               category->level = level;
-+               break;
-+            }
-+         }
-+         else
-+         {
-+            if (!warned_loglevel)
-+            {
-+                vcos_log("VC_LOGLEVEL format invalid at %s\n", env);
-+                warned_loglevel = 1;
-+            }
-+            return;
-+         }
-+      } while (env[0] != '\0');
-+   }
-+
-+   vcos_log_info( "Registered log category '%s' with level %s",
-+                  category->name,
-+                  vcos_log_level_to_string( category->level ));
-+}
-+
-+void vcos_log_unregister(VCOS_LOG_CAT_T *category)
-+{
-+   VCOS_LOG_CAT_T **pcat;
-+   vcos_mutex_lock(&lock);
-+   category->refcount--;
-+   if (category->refcount == 0)
-+   {
-+      pcat = &vcos_logging_categories;
-+      while (*pcat != category)
-+      {
-+         if (!*pcat)
-+            break;   /* possibly deregistered twice? */
-+         if ((*pcat)->next == NULL)
-+         {
-+            vcos_assert(0); /* already removed! */
-+            vcos_mutex_unlock(&lock);
-+            return;
-+         }
-+         pcat = &(*pcat)->next;
-+      }
-+      if (*pcat)
-+         *pcat = category->next;
-+
-+      vcos_log_platform_unregister(category);
-+   }
-+   vcos_mutex_unlock(&lock);
-+}
-+
-+VCOSPRE_ const VCOS_LOG_CAT_T * VCOSPOST_ vcos_log_get_default_category(void)
-+{
-+   return &dflt_log_category;
-+}
-+
-+void vcos_set_log_options(const char *opt)
-+{
-+   (void)opt;
-+}
-+
-+void vcos_log_dump_mem_impl( const VCOS_LOG_CAT_T *cat,
-+                             const char           *label,
-+                             uint32_t              addr,
-+                             const void           *voidMem,
-+                             size_t                numBytes )
-+{
-+   const uint8_t  *mem = (const uint8_t *)voidMem;
-+   size_t          offset;
-+   char            lineBuf[ 100 ];
-+   char           *s;
-+
-+   while ( numBytes > 0 )
-+   {
-+       s = lineBuf;
-+
-+       for ( offset = 0; offset < 16; offset++ )
-+       {
-+           if ( offset < numBytes )
-+           {
-+               s += vcos_snprintf( s, 4, "%02x ", mem[ offset ]);
-+           }
-+           else
-+           {
-+               s += vcos_snprintf( s, 4, "   " );
-+           }
-+       }
-+
-+       for ( offset = 0; offset < 16; offset++ )
-+       {
-+           if ( offset < numBytes )
-+           {
-+               uint8_t ch = mem[ offset ];
-+
-+               if (( ch < ' ' ) || ( ch > '~' ))
-+               {
-+                   ch = '.';
-+               }
-+               *s++ = (char)ch;
-+           }
-+       }
-+       *s++ = '\0';
-+
-+       if (( label != NULL ) && ( *label != '\0' ))
-+       {
-+          vcos_log_impl( cat, VCOS_LOG_INFO, "%s: %08x: %s", label, addr, lineBuf );
-+       }
-+       else
-+       {
-+          vcos_log_impl( cat, VCOS_LOG_INFO, "%08x: %s", addr, lineBuf );
-+       }
-+
-+       addr += 16;
-+       mem += 16;
-+       if ( numBytes > 16 )
-+       {
-+           numBytes -= 16;
-+       }
-+       else
-+       {
-+           numBytes = 0;
-+       }
-+   }
-+
-+}
-+
-+void vcos_log_impl(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, ...)
-+{
-+   va_list ap;
-+   va_start(ap,fmt);
-+   vcos_vlog_impl( cat, _level, fmt, ap );
-+   va_end(ap);
-+}
-+
-+void vcos_vlog_impl(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, va_list args)
-+{
-+   vcos_vlog_impl_func( cat, _level, fmt, args );
-+}
-+
-+void vcos_set_vlog_impl( VCOS_VLOG_IMPL_FUNC_T vlog_impl_func )
-+{
-+   if ( vlog_impl_func == NULL )
-+   {
-+      vcos_vlog_impl_func = vcos_vlog_default_impl;
-+   }
-+   else
-+   {
-+      vcos_vlog_impl_func = vlog_impl_func;
-+   }
-+}
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_mem_from_malloc.c
-@@ -0,0 +1,73 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  vcos
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - memory alloc implementation
-+=============================================================================*/
-+
-+#include "interface/vcos/vcos.h"
-+
-+#ifndef _vcos_platform_malloc
-+#include <stdlib.h>
-+#define _vcos_platform_malloc malloc
-+#define _vcos_platform_free   free
-+#endif
-+
-+typedef struct malloc_header_s {
-+   uint32_t guardword;
-+   uint32_t size;
-+   const char *description;
-+   void *ptr;
-+} MALLOC_HEADER_T;
-+
-+
-+#define MIN_ALIGN sizeof(MALLOC_HEADER_T)
-+
-+#define GUARDWORDHEAP  0xa55a5aa5
-+
-+void *vcos_generic_mem_alloc_aligned(VCOS_UNSIGNED size, VCOS_UNSIGNED align, const char *desc)
-+{
-+   int local_align = align == 0 ? 1 : align;
-+   int required_size = size + local_align + sizeof(MALLOC_HEADER_T);
-+   void *ptr = _vcos_platform_malloc(required_size);
-+   void *ret = (void *)VCOS_ALIGN_UP(((char *)ptr)+sizeof(MALLOC_HEADER_T), local_align);
-+   MALLOC_HEADER_T *h = ((MALLOC_HEADER_T *)ret)-1;
-+
-+   h->size = size;
-+   h->description = desc;
-+   h->guardword = GUARDWORDHEAP;
-+   h->ptr = ptr;
-+
-+   return ret;
-+}
-+
-+void *vcos_generic_mem_alloc(VCOS_UNSIGNED size, const char *desc)
-+{
-+   return vcos_generic_mem_alloc_aligned(size,MIN_ALIGN,desc);
-+}
-+
-+void *vcos_generic_mem_calloc(VCOS_UNSIGNED count, VCOS_UNSIGNED sz, const char *desc)
-+{
-+   uint32_t size = count*sz;
-+   void *ptr = vcos_generic_mem_alloc_aligned(size,MIN_ALIGN,desc);
-+   if (ptr)
-+   {
-+      memset(ptr, 0, size);
-+   }
-+   return ptr;
-+}
-+
-+void vcos_generic_mem_free(void *ptr)
-+{
-+   MALLOC_HEADER_T *h;
-+   if (! ptr) return;
-+
-+   h = ((MALLOC_HEADER_T *)ptr)-1;
-+   vcos_assert(h->guardword == GUARDWORDHEAP);
-+   _vcos_platform_free(h->ptr);
-+}
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_mem_from_malloc.h
-@@ -0,0 +1,54 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  VMCS Host Apps
-+Module   :  Framework - VMCS
-+
-+FILE DESCRIPTION
-+Create the vcos_malloc API from the regular system malloc/free
-+=============================================================================*/
-+
-+/**
-+  * \file
-+  *
-+  * Create the vcos malloc API from a regular system malloc/free library.
-+  *
-+  * The API lets callers specify an alignment.
-+  *
-+  * Under VideoCore this is not needed, as we can simply use the rtos_malloc routines.
-+  * But on host platforms that won't be the case.
-+  *
-+  */
-+
-+VCOSPRE_ void * VCOSPOST_  vcos_generic_mem_alloc(VCOS_UNSIGNED sz, const char *desc);
-+VCOSPRE_  void * VCOSPOST_ vcos_generic_mem_calloc(VCOS_UNSIGNED count, VCOS_UNSIGNED sz, const char *descr);
-+VCOSPRE_  void VCOSPOST_   vcos_generic_mem_free(void *ptr);
-+VCOSPRE_  void * VCOSPOST_ vcos_generic_mem_alloc_aligned(VCOS_UNSIGNED sz, VCOS_UNSIGNED align, const char *desc);
-+
-+#ifdef VCOS_INLINE_BODIES
-+
-+VCOS_INLINE_IMPL
-+void *vcos_malloc(VCOS_UNSIGNED size, const char *description) {
-+   return vcos_generic_mem_alloc(size, description);
-+}
-+
-+VCOS_INLINE_IMPL
-+void *vcos_calloc(VCOS_UNSIGNED num, VCOS_UNSIGNED size, const char *description) {
-+   return vcos_generic_mem_calloc(num, size, description);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_free(void *ptr) {
-+   vcos_generic_mem_free(ptr);
-+}
-+
-+VCOS_INLINE_IMPL
-+void * vcos_malloc_aligned(VCOS_UNSIGNED size, VCOS_UNSIGNED align, const char *description) {
-+   return vcos_generic_mem_alloc_aligned(size, align, description);
-+}
-+
-+
-+#endif /* VCOS_INLINE_BODIES */
-+
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_mutexes_are_reentrant.h
-@@ -0,0 +1,68 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - reentrant mutexes mapped directly to regular ones
-+=============================================================================*/
-+
-+#ifndef VCOS_GENERIC_REENTRANT_MUTEX_H
-+#define VCOS_GENERIC_REENTRANT_MUTEX_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+#include "interface/vcos/vcos_mutex.h"
-+
-+/**
-+ * \file
-+ *
-+ * Reentrant Mutexes directly using the native re-entrant mutex.
-+ *
-+ */
-+
-+typedef VCOS_MUTEX_T VCOS_REENTRANT_MUTEX_T;
-+
-+/* Inline forwarding functions */
-+
-+#if defined(VCOS_INLINE_BODIES)
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_reentrant_mutex_create(VCOS_REENTRANT_MUTEX_T *m, const char *name) {
-+   return vcos_mutex_create(m,name);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_reentrant_mutex_delete(VCOS_REENTRANT_MUTEX_T *m) {
-+   vcos_mutex_delete(m);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_reentrant_mutex_lock(VCOS_REENTRANT_MUTEX_T *m) {
-+   vcos_mutex_lock(m);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_reentrant_mutex_unlock(VCOS_REENTRANT_MUTEX_T *m) {
-+   vcos_mutex_unlock(m);
-+}
-+
-+VCOS_INLINE_IMPL
-+int vcos_reentrant_mutex_is_locked(VCOS_REENTRANT_MUTEX_T *m) {
-+   return vcos_mutex_is_locked(m);
-+}
-+
-+#endif
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif
-+
-+
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_thread_reaper.h
-@@ -0,0 +1,35 @@
-+/*=============================================================================
-+Copyright (c) 2010 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  vcos
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - thread reaping
-+=============================================================================*/
-+
-+#ifndef VCOS_THREAD_REAPER_H
-+#define VCOS_THREAD_REAPER_H
-+
-+#define VCOS_HAVE_THREAD_REAPER
-+
-+/** Initialise the thread reaper.
-+  */
-+VCOS_STATUS_T vcos_thread_reaper_init(void);
-+
-+/** Reap a thread. Arranges for the thread to be automatically
-+  * joined.
-+  *
-+  * @sa vcos_thread_join().
-+  *
-+  * @param thread           the thread to terminate
-+  * @param on_terminated    called after the thread has exited
-+  * @param cxt              pass back to the callback
-+  *
-+  */
-+void vcos_thread_reap(VCOS_THREAD_T *thread, void (*on_terminated)(void*), void *cxt);
-+
-+#endif
-+
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/linuxkernel/stdint.h
-@@ -0,0 +1,17 @@
-+/*=============================================================================
-+Copyright (c) 2010 Broadcom Europe Limited.
-+All rights reserved.
-+
-+FILE DESCRIPTION
-+VideoCore OS fAbstraction Layer - stdint.h C standard header
-+=============================================================================*/
-+
-+#ifndef _VCOS_PLATFORM_LINUX_STDINT_H
-+#define _VCOS_PLATFORM_LINUX_STDINT_H
-+
-+/* The Linux kernel does not have a <stdint.h> so we have to provide one of
-+   our own. */
-+
-+#include <linux/types.h> /* includes integer types */
-+
-+#endif /* _VCOS_PLATFORM_LINUX_STDINT_H */
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel.c
-@@ -0,0 +1,616 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  vcos
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - pthreads types
-+=============================================================================*/
-+
-+#define  VCOS_INLINE_BODIES
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/time.h>
-+#include <linux/pid.h>
-+#include <linux/mm.h>
-+#include <linux/version.h>
-+
-+#if defined( CONFIG_BCM_KNLLOG_SUPPORT )
-+#include <linux/broadcom/knllog.h>
-+#endif
-+#include "interface/vcos/vcos.h"
-+#ifdef HAVE_VCOS_VERSION
-+#include "interface/vcos/vcos_build_info.h"
-+#endif
-+
-+VCOS_CFG_ENTRY_T  vcos_cfg_dir;
-+VCOS_CFG_ENTRY_T  vcos_logging_cfg_dir;
-+VCOS_CFG_ENTRY_T  vcos_version_cfg;
-+
-+#ifndef VCOS_DEFAULT_STACK_SIZE
-+#define VCOS_DEFAULT_STACK_SIZE 4096
-+#endif
-+
-+static VCOS_THREAD_ATTR_T default_attrs = {
-+   0,
-+   VCOS_DEFAULT_STACK_SIZE,
-+};
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
-+static DEFINE_SEMAPHORE(lock);
-+#else
-+static DECLARE_MUTEX(lock);
-+#endif
-+
-+typedef void (*LEGACY_ENTRY_FN_T)(int, void *);
-+
-+/** Wrapper function around the real thread function. Posts the semaphore
-+  * when completed.
-+  */
-+static int vcos_thread_wrapper(void *arg)
-+{
-+   void *ret;
-+   VCOS_THREAD_T *thread = arg;
-+
-+   vcos_assert(thread->magic == VCOS_THREAD_MAGIC);
-+
-+   thread->thread.thread = current;
-+
-+   vcos_add_thread(thread);
-+
-+#ifdef VCOS_WANT_TLS_EMULATION
-+   vcos_tls_thread_register(&thread->_tls);
-+#endif
-+
-+   if (thread->legacy)
-+   {
-+      LEGACY_ENTRY_FN_T fn = (LEGACY_ENTRY_FN_T)thread->entry;
-+      fn(0,thread->arg);
-+      ret = 0;
-+   }
-+   else
-+   {
-+      ret = thread->entry(thread->arg);
-+   }
-+
-+   thread->exit_data = ret;
-+
-+   vcos_remove_thread(current);
-+
-+   /* For join and cleanup */
-+   vcos_semaphore_post(&thread->wait);
-+
-+   return 0;
-+}
-+
-+VCOS_STATUS_T vcos_thread_create(VCOS_THREAD_T *thread,
-+                                 const char *name,
-+                                 VCOS_THREAD_ATTR_T *attrs,
-+                                 VCOS_THREAD_ENTRY_FN_T entry,
-+                                 void *arg)
-+{
-+   VCOS_STATUS_T st;
-+   struct task_struct *kthread;
-+
-+   memset(thread, 0, sizeof(*thread));
-+   thread->magic     = VCOS_THREAD_MAGIC;
-+   strlcpy( thread->name, name, sizeof( thread->name ));
-+   thread->legacy    = attrs ? attrs->legacy : 0;
-+   thread->entry = entry;
-+   thread->arg = arg;
-+
-+   if (!name)
-+   {
-+      vcos_assert(0);
-+      return VCOS_EINVAL;
-+   }
-+
-+   st = vcos_semaphore_create(&thread->wait, NULL, 0);
-+   if (st != VCOS_SUCCESS)
-+   {
-+      return st;
-+   }
-+
-+   st = vcos_semaphore_create(&thread->suspend, NULL, 0);
-+   if (st != VCOS_SUCCESS)
-+   {
-+      return st;
-+   }
-+
-+   /*required for event groups */
-+   vcos_timer_create(&thread->_timer.timer, thread->name, NULL, NULL);
-+
-+   kthread = kthread_create((int (*)(void *))vcos_thread_wrapper, (void*)thread, name);
-+   vcos_assert(kthread != NULL);
-+   set_user_nice(kthread, attrs->ta_priority);
-+   thread->thread.thread = kthread;
-+   wake_up_process(kthread);
-+   return VCOS_SUCCESS;
-+}
-+
-+void vcos_thread_join(VCOS_THREAD_T *thread,
-+                             void **pData)
-+{
-+   vcos_assert(thread);
-+   vcos_assert(thread->magic == VCOS_THREAD_MAGIC);
-+
-+   thread->joined = 1;
-+
-+   vcos_semaphore_wait(&thread->wait);
-+
-+   if (pData)
-+   {
-+      *pData = thread->exit_data;
-+   }
-+
-+   /* Clean up */
-+   if (thread->stack)
-+      vcos_free(thread->stack);
-+
-+   vcos_semaphore_delete(&thread->wait);
-+   vcos_semaphore_delete(&thread->suspend);
-+
-+}
-+
-+uint32_t vcos_getmicrosecs( void )
-+{
-+   struct timeval tv;
-+/*XXX FIX ME! switch to ktime_get_ts to use MONOTONIC clock */
-+   do_gettimeofday(&tv);
-+   return (tv.tv_sec*1000000) + tv.tv_usec;
-+}
-+
-+VCOS_STATUS_T vcos_timer_init(void)
-+{
-+    return VCOS_SUCCESS;
-+}
-+
-+static const char *log_prefix[] =
-+{
-+   "",            /* VCOS_LOG_UNINITIALIZED */
-+   "",            /* VCOS_LOG_NEVER */
-+   KERN_ERR,      /* VCOS_LOG_ERROR */
-+   KERN_WARNING,  /* VCOS_LOG_WARN */
-+   KERN_INFO,     /* VCOS_LOG_INFO */
-+   KERN_INFO      /* VCOS_LOG_TRACE */
-+};
-+
-+void vcos_vlog_default_impl(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, va_list args)
-+{
-+   char *newline = strchr( fmt, '\n' );
-+   const char  *prefix;
-+   const char  *real_fmt;
-+
-+   preempt_disable();
-+   {
-+       if ( *fmt == '<' )
-+       {
-+           prefix = fmt;
-+           real_fmt= &fmt[3];
-+       }
-+       else
-+       {
-+          prefix = log_prefix[_level];
-+          real_fmt = fmt;
-+       }
-+#if defined( CONFIG_BCM_KNLLOG_SUPPORT )
-+       knllog_ventry( "vcos", real_fmt, args );
-+#endif
-+       printk( "%.3svcos: [%d]: ", prefix, current->pid );
-+       vprintk( real_fmt, args );
-+
-+       if ( newline == NULL )
-+       {
-+          printk("\n");
-+       }
-+   }
-+   preempt_enable();
-+}
-+
-+
-+const char * _vcos_log_level(void)
-+{
-+   return NULL;
-+}
-+
-+/*****************************************************************************
-+*
-+*    Displays the version information in /proc/vcos/version
-+*
-+*****************************************************************************/
-+
-+#ifdef HAVE_VCOS_VERSION
-+
-+static void show_version( VCOS_CFG_BUF_T buf, void *data )
-+{
-+   static const char* copyright = "Copyright (c) 2011 Broadcom";
-+
-+   vcos_cfg_buf_printf( buf, "Built %s %s on %s\n%s\nversion %s\n",
-+                        vcos_get_build_date(),
-+                        vcos_get_build_time(),
-+                        vcos_get_build_hostname(),
-+                        copyright,
-+                        vcos_get_build_version() );
-+}
-+
-+#endif
-+
-+/*****************************************************************************
-+*
-+*    Initialises vcos
-+*
-+*****************************************************************************/
-+
-+VCOS_STATUS_T vcos_init(void)
-+{
-+   if ( vcos_cfg_mkdir( &vcos_cfg_dir, NULL, "vcos" ) != VCOS_SUCCESS )
-+   {
-+      printk( KERN_ERR "%s: Unable to create vcos cfg entry\n", __func__ );
-+   }
-+   vcos_logging_init();
-+
-+#ifdef HAVE_VCOS_VERSION
-+   if ( vcos_cfg_create_entry( &vcos_version_cfg, &vcos_cfg_dir, "version",
-+                               show_version, NULL, NULL ) != VCOS_SUCCESS )
-+   {
-+      printk( KERN_ERR "%s: Unable to create vcos cfg entry 'version'\n", __func__ );
-+   }
-+#endif
-+
-+   return VCOS_SUCCESS;
-+}
-+
-+/*****************************************************************************
-+*
-+*    Deinitializes vcos
-+*
-+*****************************************************************************/
-+
-+void vcos_deinit(void)
-+{
-+#ifdef HAVE_VCOS_VERSION
-+   vcos_cfg_remove_entry( &vcos_version_cfg );
-+#endif
-+   vcos_cfg_remove_entry( &vcos_cfg_dir );
-+}
-+
-+void vcos_global_lock(void)
-+{
-+   down(&lock);
-+}
-+
-+void vcos_global_unlock(void)
-+{
-+   up(&lock);
-+}
-+
-+/* vcos_thread_exit() doesn't really stop this thread here
-+ *
-+ * At the moment, call to do_exit() will leak task_struct for
-+ * current thread, so we let the vcos_thread_wrapper() do the
-+ * cleanup and exit job, and we return w/o actually stopping the thread.
-+ *
-+ * ToDo: Kernel v2.6.31 onwards, it is considered safe to call do_exit()
-+ * from kthread, the implementation of which is combined in 2 patches
-+ * with commit-ids "63706172" and "cdd140bd" in oss Linux kernel tree
-+ */
-+
-+void vcos_thread_exit(void *arg)
-+{
-+   VCOS_THREAD_T *thread = vcos_thread_current();
-+
-+   vcos_assert(thread);
-+   vcos_assert(thread->magic == VCOS_THREAD_MAGIC);
-+
-+   thread->exit_data = arg;
-+}
-+
-+void vcos_thread_attr_init(VCOS_THREAD_ATTR_T *attrs)
-+{
-+   *attrs = default_attrs;
-+}
-+
-+void _vcos_task_timer_set(void (*pfn)(void *), void *cxt, VCOS_UNSIGNED ms)
-+{
-+   VCOS_THREAD_T *self = vcos_thread_current();
-+   vcos_assert(self);
-+   vcos_assert(self->_timer.pfn == NULL);
-+
-+   vcos_timer_create( &self->_timer.timer, "TaskTimer", pfn, cxt );
-+   vcos_timer_set(&self->_timer.timer, ms);
-+}
-+
-+void _vcos_task_timer_cancel(void)
-+{
-+   VCOS_THREAD_T *self = vcos_thread_current();
-+   if (self->_timer.timer.linux_timer.function)
-+   {
-+      vcos_timer_cancel(&self->_timer.timer);
-+      vcos_timer_delete(&self->_timer.timer);
-+   }
-+}
-+
-+int vcos_vsnprintf( char *buf, size_t buflen, const char *fmt, va_list ap )
-+{
-+   return vsnprintf( buf, buflen, fmt, ap );
-+}
-+
-+int vcos_snprintf(char *buf, size_t buflen, const char *fmt, ...)
-+{
-+   int ret;
-+   va_list ap;
-+   va_start(ap,fmt);
-+   ret = vsnprintf(buf, buflen, fmt, ap);
-+   va_end(ap);
-+   return ret;
-+}
-+
-+int vcos_llthread_running(VCOS_LLTHREAD_T *t) {
-+   vcos_assert(0);   /* this function only exists as a nasty hack for the video codecs! */
-+   return 1;
-+}
-+
-+static int vcos_verify_bkpts = 1;
-+
-+int vcos_verify_bkpts_enabled(void)
-+{
-+   return vcos_verify_bkpts;
-+}
-+
-+/*****************************************************************************
-+*
-+*    _vcos_log_platform_init is called from vcos_logging_init
-+*
-+*****************************************************************************/
-+
-+void _vcos_log_platform_init(void)
-+{
-+   if ( vcos_cfg_mkdir( &vcos_logging_cfg_dir, &vcos_cfg_dir, "logging" ) != VCOS_SUCCESS )
-+   {
-+      printk( KERN_ERR "%s: Unable to create logging cfg entry\n", __func__ );
-+   }
-+}
-+
-+/*****************************************************************************
-+*
-+*    Called to display the contents of a logging category.
-+*
-+*****************************************************************************/
-+
-+static void logging_show_category( VCOS_CFG_BUF_T buf, void *data )
-+{
-+   VCOS_LOG_CAT_T *category = data;
-+
-+   vcos_cfg_buf_printf( buf, "%s\n", vcos_log_level_to_string( category->level ));
-+}
-+
-+/*****************************************************************************
-+*
-+*    Called to parse content for a logging category.
-+*
-+*****************************************************************************/
-+
-+static void logging_parse_category( VCOS_CFG_BUF_T buf, void *data )
-+{
-+   VCOS_LOG_CAT_T *category = data;
-+   const char *str = vcos_cfg_buf_get_str( buf );
-+   VCOS_LOG_LEVEL_T  level;
-+
-+   if ( vcos_string_to_log_level( str, &level ) == VCOS_SUCCESS )
-+   {
-+      category->level = level;
-+   }
-+   else
-+   {
-+      printk( KERN_ERR "%s: Unrecognized logging level: '%s'\n",
-+              __func__, str );
-+   }
-+}
-+
-+/*****************************************************************************
-+*
-+*    _vcos_log_platform_register is called from vcos_log_register whenever
-+*    a new category is registered.
-+*
-+*****************************************************************************/
-+
-+void _vcos_log_platform_register(VCOS_LOG_CAT_T *category)
-+{
-+   VCOS_CFG_ENTRY_T  entry;
-+
-+   if ( vcos_cfg_create_entry( &entry, &vcos_logging_cfg_dir, category->name,
-+                               logging_show_category, logging_parse_category,
-+                               category ) != VCOS_SUCCESS )
-+   {
-+      printk( KERN_ERR "%s: Unable to create cfg entry for logging category '%s'\n",
-+              __func__, category->name );
-+      category->platform_data = NULL;
-+   }
-+   else
-+   {
-+      category->platform_data = entry;
-+   }
-+}
-+
-+/*****************************************************************************
-+*
-+*    _vcos_log_platform_unregister is called from vcos_log_unregister whenever
-+*    a new category is unregistered.
-+*
-+*****************************************************************************/
-+
-+void _vcos_log_platform_unregister(VCOS_LOG_CAT_T *category)
-+{
-+   VCOS_CFG_ENTRY_T  entry;
-+
-+   entry = category->platform_data;
-+   if ( entry != NULL )
-+   {
-+      if ( vcos_cfg_remove_entry( &entry ) != VCOS_SUCCESS )
-+      {
-+         printk( KERN_ERR "%s: Unable to remove cfg entry for logging category '%s'\n",
-+                 __func__, category->name );
-+      }
-+   }
-+}
-+
-+/*****************************************************************************
-+*
-+*    Allocate memory.
-+*
-+*****************************************************************************/
-+
-+void *vcos_platform_malloc( VCOS_UNSIGNED required_size )
-+{
-+   if ( required_size >= ( 2 * PAGE_SIZE ))
-+   {
-+      /* For larger allocations, use vmalloc, whose underlying allocator
-+       * returns pages
-+       */
-+
-+      return vmalloc( required_size );
-+   }
-+
-+   /* For smaller allocation, use kmalloc */
-+
-+   return kmalloc( required_size, GFP_KERNEL );
-+}
-+
-+/*****************************************************************************
-+*
-+*    Free previously allocated memory
-+*
-+*****************************************************************************/
-+
-+void  vcos_platform_free( void *ptr )
-+{
-+   if (((unsigned long)ptr >= VMALLOC_START )
-+   &&  ((unsigned long)ptr < VMALLOC_END ))
-+   {
-+      vfree( ptr );
-+   }
-+   else
-+   {
-+      kfree( ptr );
-+   }
-+}
-+
-+/*****************************************************************************
-+*
-+*    Execute a routine exactly once.
-+*
-+*****************************************************************************/
-+
-+VCOS_STATUS_T vcos_once(VCOS_ONCE_T *once_control,
-+                        void (*init_routine)(void))
-+{
-+   /* In order to be thread-safe we need to re-test *once_control
-+    * inside the lock. The outer test is basically an optimization
-+    * so that once it is initialized we don't need to waste time
-+    * trying to acquire the lock.
-+    */
-+
-+   if ( *once_control == 0 )
-+   {
-+       vcos_global_lock();
-+       if ( *once_control == 0 )
-+       {
-+           init_routine();
-+           *once_control = 1;
-+       }
-+       vcos_global_unlock();
-+   }
-+
-+   return VCOS_SUCCESS;
-+}
-+
-+/*****************************************************************************
-+*
-+*    String duplication routine.
-+*
-+*****************************************************************************/
-+
-+char *vcos_strdup(const char *str)
-+{
-+    return kstrdup(str, GFP_KERNEL);
-+}
-+
-+
-+/* Export functions for modules to use */
-+EXPORT_SYMBOL( vcos_init );
-+
-+EXPORT_SYMBOL( vcos_semaphore_trywait );
-+EXPORT_SYMBOL( vcos_semaphore_post );
-+EXPORT_SYMBOL( vcos_semaphore_create );
-+EXPORT_SYMBOL( vcos_semaphore_wait );
-+EXPORT_SYMBOL( vcos_semaphore_delete );
-+
-+EXPORT_SYMBOL( vcos_log_impl );
-+EXPORT_SYMBOL( vcos_vlog_impl );
-+EXPORT_SYMBOL( vcos_vlog_default_impl );
-+EXPORT_SYMBOL( vcos_log_get_default_category );
-+EXPORT_SYMBOL( vcos_log_register );
-+EXPORT_SYMBOL( vcos_log_unregister );
-+EXPORT_SYMBOL( vcos_logging_init );
-+EXPORT_SYMBOL( vcos_log_level_to_string );
-+EXPORT_SYMBOL( vcos_string_to_log_level );
-+EXPORT_SYMBOL( vcos_log_dump_mem_impl );
-+
-+EXPORT_SYMBOL( vcos_event_create );
-+EXPORT_SYMBOL( vcos_event_delete );
-+EXPORT_SYMBOL( vcos_event_flags_set );
-+EXPORT_SYMBOL( vcos_event_signal );
-+EXPORT_SYMBOL( vcos_event_wait );
-+EXPORT_SYMBOL( vcos_event_try );
-+
-+EXPORT_SYMBOL( vcos_getmicrosecs );
-+
-+EXPORT_SYMBOL( vcos_strcasecmp );
-+EXPORT_SYMBOL( vcos_snprintf );
-+EXPORT_SYMBOL( vcos_vsnprintf );
-+
-+EXPORT_SYMBOL( vcos_thread_current );
-+EXPORT_SYMBOL( vcos_thread_join );
-+EXPORT_SYMBOL( vcos_thread_create );
-+EXPORT_SYMBOL( vcos_thread_set_priority );
-+EXPORT_SYMBOL( vcos_thread_exit );
-+EXPORT_SYMBOL( vcos_once );
-+
-+EXPORT_SYMBOL( vcos_thread_attr_init );
-+EXPORT_SYMBOL( vcos_thread_attr_setpriority );
-+EXPORT_SYMBOL( vcos_thread_attr_settimeslice );
-+EXPORT_SYMBOL( vcos_thread_attr_setstacksize );
-+EXPORT_SYMBOL( _vcos_thread_attr_setlegacyapi );
-+
-+EXPORT_SYMBOL( vcos_event_flags_create );
-+EXPORT_SYMBOL( vcos_event_flags_delete );
-+EXPORT_SYMBOL( vcos_event_flags_get );
-+
-+EXPORT_SYMBOL( vcos_sleep );
-+
-+EXPORT_SYMBOL( vcos_calloc );
-+EXPORT_SYMBOL( vcos_malloc );
-+EXPORT_SYMBOL( vcos_malloc_aligned );
-+EXPORT_SYMBOL( vcos_free );
-+
-+EXPORT_SYMBOL( vcos_mutex_create );
-+EXPORT_SYMBOL( vcos_mutex_delete );
-+EXPORT_SYMBOL( vcos_mutex_lock );
-+EXPORT_SYMBOL( vcos_mutex_unlock );
-+EXPORT_SYMBOL( vcos_mutex_trylock );
-+
-+EXPORT_SYMBOL( vcos_timer_cancel );
-+EXPORT_SYMBOL( vcos_timer_create );
-+EXPORT_SYMBOL( vcos_timer_delete );
-+EXPORT_SYMBOL( vcos_timer_set );
-+
-+EXPORT_SYMBOL( vcos_atomic_flags_create );
-+EXPORT_SYMBOL( vcos_atomic_flags_delete );
-+EXPORT_SYMBOL( vcos_atomic_flags_or );
-+EXPORT_SYMBOL( vcos_atomic_flags_get_and_clear );
-+
-+EXPORT_SYMBOL( vcos_verify_bkpts_enabled );
-+
-+EXPORT_SYMBOL( vcos_strdup );
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel_cfg.c
-@@ -0,0 +1,332 @@
-+/*****************************************************************************
-+* Copyright 2009 - 2010 Broadcom Corporation.  All rights reserved.
-+*
-+* Unless you and Broadcom execute a separate written software license
-+* agreement governing use of this software, this software is licensed to you
-+* under the terms of the GNU General Public License version 2, available at
-+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-+*
-+* Notwithstanding the above, under no circumstances may you combine this
-+* software in any way with any other Broadcom software provided under a
-+* license other than the GPL, without Broadcom's express prior written
-+* consent.
-+*****************************************************************************/
-+
-+#include "interface/vcos/vcos.h"
-+#include <linux/module.h>
-+#include <linux/proc_fs.h>
-+#include <linux/seq_file.h>
-+#include <asm/uaccess.h>
-+
-+struct opaque_vcos_cfg_buf_t
-+{
-+    struct seq_file *seq;
-+    char            *charBuf;
-+};
-+
-+struct opaque_vcos_cfg_entry_t
-+{
-+    struct proc_dir_entry *pde;
-+    struct proc_dir_entry *parent_pde;
-+    VCOS_CFG_SHOW_FPTR     showFunc;
-+    VCOS_CFG_PARSE_FPTR    parseFunc;
-+    void                  *data;
-+    const char            *name;
-+};
-+
-+/***************************************************************************** 
-+* 
-+*    cfg_proc_show
-+*  
-+*****************************************************************************/
-+
-+static int cfg_proc_show( struct seq_file *s, void *v )
-+{
-+    VCOS_CFG_ENTRY_T                entry;
-+    struct opaque_vcos_cfg_buf_t    buf;
-+
-+    entry = s->private;
-+
-+    if ( entry->showFunc )
-+    {
-+        memset( &buf, 0, sizeof( buf ));
-+        buf.seq = s;
-+
-+        entry->showFunc( &buf, entry->data );
-+    }
-+
-+    return 0;
-+}
-+
-+/***************************************************************************** 
-+* 
-+*    cfg_proc_write
-+*  
-+*****************************************************************************/
-+
-+static ssize_t cfg_proc_write( struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
-+{
-+    VCOS_CFG_ENTRY_T                entry = PDE(file->f_path.dentry->d_inode)->data;
-+    char                           *charBuf;
-+    struct opaque_vcos_cfg_buf_t    buf;
-+    size_t                          len;
-+
-+    if ( entry->parseFunc != NULL )
-+    {
-+        /* The number 4000 is rather arbitrary. It just needs to be bigger than any input
-+         * string we expect to use.
-+         */
-+
-+        len = count;
-+        if ( count > 4000 )
-+        {
-+            len = 4000;
-+        }
-+
-+        /* Allocate a kernel buffer to contain the string being written. */
-+
-+        charBuf = kmalloc( len + 1, GFP_KERNEL );
-+        if ( copy_from_user( charBuf, buffer, len ))
-+        {
-+            kfree( charBuf );
-+            return -EFAULT;
-+        }
-+
-+        /* echo puts a trailing newline in the buffer - strip it out. */
-+
-+        if (( len > 0 ) && ( charBuf[ len - 1 ] == '\n' ))
-+        {
-+            len--;
-+        }
-+        charBuf[len] = '\0';
-+
-+        memset( &buf, 0, sizeof( buf ));
-+        buf.charBuf = charBuf;
-+
-+        entry->parseFunc( &buf, entry->data );
-+        kfree( charBuf );
-+    }
-+    return count;
-+}
-+
-+/***************************************************************************** 
-+* 
-+*    cfg_proc_open
-+*  
-+*****************************************************************************/
-+
-+static int cfg_proc_open( struct inode *inode, struct file *file )
-+{
-+    return single_open( file, cfg_proc_show, PDE(inode)->data );
-+}
-+
-+static const struct file_operations cfg_proc_fops = 
-+{
-+    .open       = cfg_proc_open,
-+    .read       = seq_read,
-+    .llseek     = seq_lseek,
-+    .release    = single_release,
-+    .write      = cfg_proc_write,
-+};
-+
-+/***************************************************************************** 
-+* 
-+*    vcos_cfg_mkdir
-+*  
-+*****************************************************************************/
-+
-+VCOS_STATUS_T vcos_cfg_mkdir( VCOS_CFG_ENTRY_T *entryp,
-+                              VCOS_CFG_ENTRY_T *parent,
-+                              const char *dirName )
-+{
-+    VCOS_CFG_ENTRY_T    entry;
-+
-+    if (( entry = kzalloc( sizeof( *entry ), GFP_KERNEL )) == NULL )
-+    {
-+        return VCOS_ENOMEM;
-+    }
-+
-+    if ( parent == NULL )
-+    {
-+        entry->pde = proc_mkdir( dirName, NULL );
-+    }
-+    else
-+    {
-+        entry->pde = proc_mkdir( dirName, (*parent)->pde );
-+        entry->parent_pde = (*parent)->pde;
-+    }
-+    if ( entry->pde == NULL )
-+    {
-+        kfree( entry );
-+        return VCOS_ENOMEM;
-+    }
-+
-+    entry->name = dirName;
-+
-+    *entryp = entry;
-+    return VCOS_SUCCESS;
-+}
-+
-+/***************************************************************************** 
-+* 
-+*    vcos_cfg_create_entry
-+*  
-+*****************************************************************************/
-+
-+VCOS_STATUS_T vcos_cfg_create_entry( VCOS_CFG_ENTRY_T *entryp,
-+                                     VCOS_CFG_ENTRY_T *parent,
-+                                     const char *entryName,
-+                                     VCOS_CFG_SHOW_FPTR showFunc,
-+                                     VCOS_CFG_PARSE_FPTR parseFunc,
-+                                     void *data )
-+{
-+    VCOS_CFG_ENTRY_T    entry;
-+    mode_t              mode;
-+
-+    *entryp = NULL;
-+
-+    if (( entry = kzalloc( sizeof( *entry ), GFP_KERNEL )) == NULL )
-+    {
-+        return VCOS_ENOMEM;
-+    }
-+
-+    mode = 0;
-+    if ( showFunc != NULL )
-+    {
-+        mode |= 0444;
-+    }
-+    if ( parseFunc != NULL )
-+    {
-+        mode |= 0200;
-+    }
-+    
-+    if ( parent == NULL )
-+    {
-+        entry->pde = create_proc_entry( entryName, mode, NULL );
-+    }
-+    else
-+    {
-+        entry->pde = create_proc_entry( entryName, mode, (*parent)->pde );
-+        entry->parent_pde = (*parent)->pde;
-+    }
-+    if ( entry->pde == NULL )
-+    {
-+        kfree( entry );
-+        return -ENOMEM;
-+    }
-+    entry->showFunc = showFunc;
-+    entry->parseFunc = parseFunc;
-+    entry->data = data;
-+    entry->name = entryName;
-+
-+    entry->pde->data = entry;
-+    entry->pde->proc_fops = &cfg_proc_fops;
-+    
-+    *entryp = entry;
-+    return VCOS_SUCCESS;    
-+}
-+
-+/***************************************************************************** 
-+* 
-+*    vcos_cfg_remove_entry
-+*  
-+*****************************************************************************/
-+
-+VCOS_STATUS_T vcos_cfg_remove_entry( VCOS_CFG_ENTRY_T *entryp )
-+{
-+    if (( entryp != NULL ) && ( *entryp != NULL ))
-+    {
-+        remove_proc_entry( (*entryp)->name, (*entryp)->parent_pde );
-+
-+        kfree( *entryp );
-+        *entryp = NULL;
-+    }
-+
-+    return VCOS_SUCCESS;
-+}
-+
-+/***************************************************************************** 
-+* 
-+*    vcos_cfg_is_entry_created
-+*  
-+*****************************************************************************/
-+
-+int vcos_cfg_is_entry_created( VCOS_CFG_ENTRY_T entry )
-+{
-+    return ( entry != NULL ) && ( entry->pde != NULL );
-+}
-+
-+/***************************************************************************** 
-+* 
-+*    vcos_cfg_buf_printf
-+*  
-+*****************************************************************************/
-+
-+void vcos_cfg_buf_printf( VCOS_CFG_BUF_T buf, const char *fmt, ... )
-+{
-+    struct seq_file *m = buf->seq;
-+
-+    /* Bah - there is no seq_vprintf */
-+
-+    va_list args;
-+    int len;
-+
-+    if (m->count < m->size) {
-+        va_start(args, fmt);
-+        len = vsnprintf(m->buf + m->count, m->size - m->count, fmt, args);
-+        va_end(args);
-+        if (m->count + len < m->size) {
-+            m->count += len;
-+            return;
-+        }
-+    }
-+    m->count = m->size;
-+}
-+
-+/***************************************************************************** 
-+* 
-+*    vcos_cfg_buf_get_str
-+*  
-+*****************************************************************************/
-+
-+char *vcos_cfg_buf_get_str( VCOS_CFG_BUF_T buf )
-+{
-+    return buf->charBuf;
-+}
-+
-+/***************************************************************************** 
-+* 
-+*    vcos_cfg_get_proc_entry
-+*  
-+*    This function is only created for a couple of backwards compatibility '
-+*    issues and shouldn't normally be used.
-+*  
-+*****************************************************************************/
-+
-+void *vcos_cfg_get_proc_entry( VCOS_CFG_ENTRY_T entry )
-+{
-+    return entry->pde;
-+}
-+
-+/***************************************************************************** 
-+* 
-+*    vcos_cfg_get_entry_name
-+*  
-+*****************************************************************************/
-+
-+const char *vcos_cfg_get_entry_name( VCOS_CFG_ENTRY_T entry )
-+{
-+   return entry->pde->name;
-+}
-+
-+
-+EXPORT_SYMBOL( vcos_cfg_mkdir );
-+EXPORT_SYMBOL( vcos_cfg_create_entry );
-+EXPORT_SYMBOL( vcos_cfg_remove_entry );
-+EXPORT_SYMBOL( vcos_cfg_get_entry_name );
-+EXPORT_SYMBOL( vcos_cfg_is_entry_created );
-+EXPORT_SYMBOL( vcos_cfg_buf_printf );
-+EXPORT_SYMBOL( vcos_cfg_buf_get_str );
-+
-+EXPORT_SYMBOL_GPL( vcos_cfg_get_proc_entry );
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel_misc.c
-@@ -0,0 +1,113 @@
-+// #############################################################################
-+// START #######################################################################
-+/*****************************************************************************
-+* Copyright 2009 - 2010 Broadcom Corporation.  All rights reserved.
-+*
-+* Unless you and Broadcom execute a separate written software license
-+* agreement governing use of this software, this software is licensed to you
-+* under the terms of the GNU General Public License version 2, available at
-+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-+*
-+* Notwithstanding the above, under no circumstances may you combine this
-+* software in any way with any other Broadcom software provided under a
-+* license other than the GPL, without Broadcom's express prior written
-+* consent.
-+*****************************************************************************/
-+
-+#include "interface/vcos/vcos.h"
-+#include <linux/sched.h>
-+#include <linux/module.h>
-+#include <linux/freezer.h>
-+#include <linux/string.h>
-+#include <linux/slab.h>
-+
-+/***************************************************************************** 
-+* 
-+*        vcos_semaphore_wait_freezable
-+*  
-+*****************************************************************************/
-+
-+VCOS_STATUS_T vcos_semaphore_wait_freezable(VCOS_SEMAPHORE_T *sem)
-+{
-+    int rval, sig_pended = 0;
-+    unsigned long flags;
-+    struct task_struct *task = current;
-+
-+    while (1) {
-+       rval = down_interruptible((struct semaphore *)sem);
-+       if (rval == 0) { /* down now */
-+          break;
-+       } else {
-+          if (freezing(current)) {
-+             try_to_freeze();
-+          } else {
-+             spin_lock_irqsave(&task->sighand->siglock, flags);
-+             if (test_tsk_thread_flag(task, TIF_SIGPENDING)) {
-+                clear_tsk_thread_flag(task, TIF_SIGPENDING);
-+                sig_pended = 1;
-+             }
-+             spin_unlock_irqrestore(&task->sighand->siglock, flags);
-+          }
-+       }
-+    }
-+
-+    if (sig_pended) {
-+       spin_lock_irqsave(&task->sighand->siglock, flags);
-+       set_tsk_thread_flag(task, TIF_SIGPENDING);
-+       spin_unlock_irqrestore(&task->sighand->siglock, flags);
-+    }
-+
-+    return 0;
-+}
-+
-+EXPORT_SYMBOL( vcos_semaphore_wait_freezable );
-+
-+/***************************************************************************** 
-+* 
-+*  vcos_kmalloc
-+*  
-+*  We really need to convert malloc to do kmalloc or vmalloc based on the
-+*  size, but for now we'll add a separate function.
-+*  
-+*****************************************************************************/
-+
-+void *vcos_kmalloc(VCOS_UNSIGNED size, const char *description)
-+{
-+   (void)description;
-+
-+   return kmalloc( size, GFP_KERNEL );
-+}
-+
-+/***************************************************************************** 
-+* 
-+*  vcos_kmalloc
-+*  
-+*  We really need to convert malloc to do kmalloc or vmalloc based on the
-+*  size, but for now we'll add a separate function.
-+*  
-+*****************************************************************************/
-+
-+void *vcos_kcalloc(VCOS_UNSIGNED num, VCOS_UNSIGNED size, const char *description)
-+{
-+   (void)description;
-+
-+   return kzalloc( num * size, GFP_KERNEL );
-+}
-+
-+/***************************************************************************** 
-+* 
-+*  vcos_kfree
-+*  
-+*****************************************************************************/
-+
-+void vcos_kfree(void *ptr)
-+{
-+   kfree( ptr );
-+}
-+
-+EXPORT_SYMBOL( vcos_kmalloc );
-+EXPORT_SYMBOL( vcos_kcalloc );
-+EXPORT_SYMBOL( vcos_kfree );
-+
-+// END #########################################################################
-+// #############################################################################
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_mod_init.c
-@@ -0,0 +1,64 @@
-+/*****************************************************************************
-+* Copyright 2006 - 2008 Broadcom Corporation.  All rights reserved.
-+*
-+* Unless you and Broadcom execute a separate written software license
-+* agreement governing use of this software, this software is licensed to you
-+* under the terms of the GNU General Public License version 2, available at
-+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). 
-+*
-+* Notwithstanding the above, under no circumstances may you combine this
-+* software in any way with any other Broadcom software provided under a
-+* license other than the GPL, without Broadcom's express prior written
-+* consent.
-+****************************************************************************/
-+
-+/* ---- Include Files ---------------------------------------------------- */
-+
-+#include "interface/vcos/vcos.h"
-+#include <linux/module.h>
-+
-+/* ---- Public Variables ------------------------------------------------- */
-+
-+/* ---- Private Constants and Types -------------------------------------- */
-+
-+/* ---- Private Variables ------------------------------------------------ */
-+
-+/* ---- Private Function Prototypes -------------------------------------- */
-+
-+/* ---- Functions -------------------------------------------------------- */
-+
-+/****************************************************************************
-+*
-+*   Called to perform module initialization when the module is loaded
-+*
-+***************************************************************************/
-+
-+static int __init vcos_mod_init( void )
-+{
-+    printk( KERN_INFO "VCOS Module\n" );
-+
-+    vcos_init();
-+    return 0;
-+}
-+
-+/****************************************************************************
-+*
-+*   Called to perform module cleanup when the module is unloaded.
-+*
-+***************************************************************************/
-+
-+static void __exit vcos_mod_exit( void )
-+{
-+    vcos_deinit();
-+}
-+
-+/****************************************************************************/
-+
-+module_init( vcos_mod_init );
-+module_exit( vcos_mod_exit );
-+
-+MODULE_AUTHOR("Broadcom");
-+MODULE_DESCRIPTION( "VCOS Module Functions" );
-+MODULE_LICENSE( "GPL" );
-+MODULE_VERSION( "1.0" );
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_platform.h
-@@ -0,0 +1,496 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  vcos
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - Linux kernel (partial) implementation.
-+=============================================================================*/
-+
-+/* Do not include this file directly - instead include it via vcos.h */
-+
-+/** @file
-+  *
-+  * Linux kernel (partial) implementation of VCOS.
-+  *
-+  */
-+
-+#ifndef VCOS_PLATFORM_H
-+#define VCOS_PLATFORM_H
-+
-+#include <linux/types.h>
-+#include <linux/semaphore.h>
-+#include <linux/mutex.h>
-+#include <asm/bitops.h>
-+#include <linux/kthread.h>
-+#include <linux/wait.h>
-+#include <linux/vmalloc.h>
-+#include <linux/jiffies.h>
-+#include <linux/delay.h>
-+#include <linux/string.h>
-+#include <linux/types.h>
-+#include <linux/interrupt.h>
-+#include <linux/random.h>
-+#include <linux/sched.h>
-+#include <linux/ctype.h>
-+#include <linux/uaccess.h>
-+#include <linux/time.h>  /* for time_t */
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+
-+#define VCOS_HAVE_RTOS         1
-+#define VCOS_HAVE_SEMAPHORE    1
-+#define VCOS_HAVE_EVENT        1
-+#define VCOS_HAVE_QUEUE        0
-+#define VCOS_HAVE_LEGACY_ISR   0
-+#define VCOS_HAVE_TIMER        1
-+#define VCOS_HAVE_CANCELLATION_SAFE_TIMER 0
-+#define VCOS_HAVE_MEMPOOL      0
-+#define VCOS_HAVE_ISR          0
-+#define VCOS_HAVE_ATOMIC_FLAGS 1
-+#define VCOS_HAVE_BLOCK_POOL   0
-+#define VCOS_HAVE_ONCE         1
-+#define VCOS_HAVE_FILE         0
-+#define VCOS_HAVE_USER_BUF     0
-+#define VCOS_HAVE_CFG          1
-+#define VCOS_HAVE_SPINLOCK     0
-+#define VCOS_HAVE_CMD          1
-+#define VCOS_HAVE_EVENT_FLAGS  1
-+
-+/* Exclude many VCOS classes which don't have predicates */
-+#define VCOS_TLS_H
-+#define VCOS_NAMED_MUTEX_H
-+#define VCOS_REENTRANT_MUTEX_H
-+#define VCOS_NAMED_SEMAPHORE_H
-+#define VCOS_QUICKSLOW_MUTEX_H
-+/*#define VCOS_INIT_H */
-+/*#define VCOS_MEM_H */
-+/*#define VCOS_STRING_H */
-+
-+typedef struct semaphore      VCOS_SEMAPHORE_T;
-+typedef struct semaphore      VCOS_EVENT_T;
-+typedef struct mutex          VCOS_MUTEX_T;
-+typedef volatile int          VCOS_ONCE_T;
-+
-+typedef unsigned int          VCOS_UNSIGNED;
-+typedef unsigned int          VCOS_OPTION;
-+typedef atomic_t              VCOS_ATOMIC_FLAGS_T;
-+
-+typedef struct
-+{
-+    struct  timer_list      linux_timer;
-+    void                   *context;
-+    void                  (*expiration_routine)(void *context);
-+
-+} VCOS_TIMER_T;
-+
-+typedef struct VCOS_LLTHREAD_T
-+{
-+   struct task_struct *thread;             /**< The thread itself */
-+   VCOS_SEMAPHORE_T suspend;     /**< For support event groups and similar - a per thread semaphore */
-+} VCOS_LLTHREAD_T;
-+
-+typedef enum
-+{
-+    VCOS_O_RDONLY   = 00000000,
-+    VCOS_O_WRONLY   = 00000001,
-+    VCOS_O_RDWR     = 00000002,
-+    VCOS_O_TRUNC    = 00001000,
-+} VCOS_FILE_FLAGS_T;
-+
-+typedef struct file *VCOS_FILE_T;
-+
-+#define VCOS_SUSPEND          -1
-+#define VCOS_NO_SUSPEND       0
-+
-+#define VCOS_START 1
-+#define VCOS_NO_START 0
-+
-+#define VCOS_THREAD_PRI_MIN   -20
-+#define VCOS_THREAD_PRI_MAX   19
-+
-+#define VCOS_THREAD_PRI_INCREASE -1
-+#define VCOS_THREAD_PRI_HIGHEST  VCOS_THREAD_PRI_MIN
-+#define VCOS_THREAD_PRI_LOWEST   VCOS_THREAD_PRI_MAX
-+#define VCOS_THREAD_PRI_NORMAL ((VCOS_THREAD_PRI_MAX+VCOS_THREAD_PRI_MIN)/2)
-+#define VCOS_THREAD_PRI_ABOVE_NORMAL (VCOS_THREAD_PRI_NORMAL + VCOS_THREAD_PRI_INCREASE)
-+#define VCOS_THREAD_PRI_REALTIME VCOS_THREAD_PRI_HIGHEST
-+
-+#define _VCOS_AFFINITY_DEFAULT 0
-+#define _VCOS_AFFINITY_CPU0 0
-+#define _VCOS_AFFINITY_CPU1 0
-+#define _VCOS_AFFINITY_MASK 0
-+#define VCOS_CAN_SET_STACK_ADDR  0
-+
-+#define VCOS_TICKS_PER_SECOND HZ
-+
-+#include "interface/vcos/generic/vcos_generic_event_flags.h"
-+#include "interface/vcos/generic/vcos_mem_from_malloc.h"
-+#include "interface/vcos/generic/vcos_joinable_thread_from_plain.h"
-+
-+/***********************************************************
-+ *
-+ * Memory allcoation
-+ *
-+ ***********************************************************/
-+
-+#define  _vcos_platform_malloc   vcos_platform_malloc
-+#define  _vcos_platform_free     vcos_platform_free
-+
-+void *vcos_platform_malloc( VCOS_UNSIGNED required_size );
-+void  vcos_platform_free( void *ptr );
-+
-+#if defined(VCOS_INLINE_BODIES)
-+
-+#undef VCOS_ASSERT_LOGGING_DISABLE
-+#define VCOS_ASSERT_LOGGING_DISABLE 1
-+
-+/***********************************************************
-+ *
-+ * Counted Semaphores
-+ *
-+ ***********************************************************/
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_semaphore_wait(VCOS_SEMAPHORE_T *sem) {
-+   int ret = down_interruptible(sem);
-+   if ( ret == 0 )
-+      /* Success */
-+      return VCOS_SUCCESS;
-+   else if ( ret == -EINTR )
-+      /* Interrupted */
-+      return VCOS_EINTR;
-+   else
-+      /* Default (timeout) */
-+      return VCOS_EAGAIN;
-+}
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_semaphore_trywait(VCOS_SEMAPHORE_T *sem) {
-+   if (down_trylock(sem) != 0)
-+      return VCOS_EAGAIN;
-+   return VCOS_SUCCESS;
-+}
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_semaphore_create(VCOS_SEMAPHORE_T *sem,
-+                                    const char *name,
-+                                    VCOS_UNSIGNED initial_count) {
-+   sema_init(sem, initial_count);
-+   return VCOS_SUCCESS;
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_semaphore_delete(VCOS_SEMAPHORE_T *sem) {
-+}
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_semaphore_post(VCOS_SEMAPHORE_T *sem) {
-+   up(sem);
-+   return VCOS_SUCCESS;
-+}
-+
-+/***********************************************************
-+ *
-+ * Threads
-+ *
-+ ***********************************************************/
-+
-+#include "vcos_thread_map.h"
-+
-+VCOS_INLINE_IMPL
-+VCOS_LLTHREAD_T *vcos_llthread_current(void) {
-+        return &vcos_kthread_current()->thread;
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_llthread_resume(VCOS_LLTHREAD_T *thread) {
-+   vcos_assert(0);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_sleep(uint32_t ms) {
-+   msleep(ms);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_thread_set_priority(VCOS_THREAD_T *thread, VCOS_UNSIGNED p) {
-+   /* not implemented */
-+}
-+VCOS_INLINE_IMPL
-+VCOS_UNSIGNED vcos_thread_get_priority(VCOS_THREAD_T *thread) {
-+   /* not implemented */
-+   return 0;
-+}
-+
-+/***********************************************************
-+ *
-+ * Miscellaneous
-+ *
-+ ***********************************************************/
-+
-+VCOS_INLINE_IMPL
-+int vcos_strcasecmp(const char *s1, const char *s2) {
-+   return strcasecmp(s1,s2);
-+}
-+
-+
-+/***********************************************************
-+ *
-+ * Mutexes
-+ *
-+ ***********************************************************/
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_mutex_create(VCOS_MUTEX_T *m, const char *name) {
-+   mutex_init(m);
-+   return VCOS_SUCCESS;
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_mutex_delete(VCOS_MUTEX_T *m) {
-+}
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_mutex_lock(VCOS_MUTEX_T *m) {
-+   int ret = mutex_lock_interruptible(m);
-+   if ( ret == 0 )
-+      /* Success */
-+      return VCOS_SUCCESS;
-+   else if ( ret == -EINTR )
-+      /* Interrupted */
-+      return VCOS_EINTR;
-+   else
-+      /* Default */
-+      return VCOS_EAGAIN;
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_mutex_unlock(VCOS_MUTEX_T *m) {
-+   mutex_unlock(m);
-+}
-+
-+VCOS_INLINE_IMPL
-+int vcos_mutex_is_locked(VCOS_MUTEX_T *m) {
-+   if (mutex_trylock(m) != 0)
-+      return 1; /* it was locked */
-+   mutex_unlock(m);
-+   /* it wasn't locked */
-+   return 0;
-+}
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_mutex_trylock(VCOS_MUTEX_T *m) {
-+   if (mutex_trylock(m) == 0)
-+      return VCOS_SUCCESS;
-+   else
-+      return VCOS_EAGAIN;
-+}
-+
-+/* For supporting event groups - per thread semaphore */
-+VCOS_INLINE_IMPL
-+void _vcos_thread_sem_wait(void) {
-+   VCOS_THREAD_T *t = vcos_thread_current();
-+   vcos_semaphore_wait(&t->suspend);
-+}
-+
-+VCOS_INLINE_IMPL
-+void _vcos_thread_sem_post(VCOS_THREAD_T *target) {
-+   vcos_semaphore_post(&target->suspend);
-+}
-+
-+/***********************************************************
-+ *
-+ * Events
-+ *
-+ ***********************************************************/
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_event_create(VCOS_EVENT_T *event, const char *debug_name)
-+{
-+   sema_init(event, 0);
-+   return VCOS_SUCCESS;
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_event_signal(VCOS_EVENT_T *event)
-+{
-+   up(event);
-+}
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_event_wait(VCOS_EVENT_T *event)
-+{
-+   int ret = down_interruptible(event);
-+   if ( ret == -EINTR )
-+      /* Interrupted */
-+      return VCOS_EINTR;
-+   else if (ret != 0)
-+      /* Default (timeout) */
-+      return VCOS_EAGAIN;
-+   /* Emulate a maximum count of 1 by removing any extra upness */
-+   while (down_trylock(event) == 0) continue;
-+   return VCOS_SUCCESS;
-+}
-+
-+VCOS_INLINE_DECL
-+VCOS_STATUS_T vcos_event_try(VCOS_EVENT_T *event)
-+{
-+   return (down_trylock(event) == 0) ? VCOS_SUCCESS : VCOS_EAGAIN;
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_event_delete(VCOS_EVENT_T *event)
-+{
-+}
-+
-+/***********************************************************
-+ *
-+ * Timers
-+ *
-+ ***********************************************************/
-+
-+VCOS_INLINE_DECL
-+void vcos_timer_linux_func(unsigned long data)
-+{
-+    VCOS_TIMER_T    *vcos_timer = (VCOS_TIMER_T *)data;
-+
-+    vcos_timer->expiration_routine( vcos_timer->context );
-+}
-+
-+VCOS_INLINE_DECL
-+VCOS_STATUS_T vcos_timer_create(VCOS_TIMER_T *timer,
-+                                const char *name,
-+                                void (*expiration_routine)(void *context),
-+                                void *context) {
-+      init_timer(&timer->linux_timer);
-+      timer->linux_timer.data = (unsigned long)timer;
-+      timer->linux_timer.function = vcos_timer_linux_func;
-+
-+    timer->context = context;
-+    timer->expiration_routine = expiration_routine;
-+
-+    return VCOS_SUCCESS;
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_timer_set(VCOS_TIMER_T *timer, VCOS_UNSIGNED delay_ms) {
-+      timer->linux_timer.expires = jiffies + msecs_to_jiffies(delay_ms);
-+       add_timer(&timer->linux_timer);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_timer_cancel(VCOS_TIMER_T *timer) {
-+     del_timer(&timer->linux_timer);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_timer_reset(VCOS_TIMER_T *timer, VCOS_UNSIGNED delay_ms) {
-+    del_timer_sync(&timer->linux_timer);
-+    timer->linux_timer.expires = jiffies + msecs_to_jiffies(delay_ms);
-+    add_timer(&timer->linux_timer);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_timer_delete(VCOS_TIMER_T *timer) {
-+    timer->context = NULL;
-+    timer->expiration_routine = NULL;
-+    timer->linux_timer.function = NULL;
-+    timer->linux_timer.data = 0;
-+    return;
-+}
-+
-+VCOS_INLINE_IMPL
-+VCOS_UNSIGNED vcos_process_id_current(void) {
-+   return (VCOS_UNSIGNED)current->pid;
-+}
-+
-+
-+VCOS_INLINE_IMPL
-+int vcos_in_interrupt(void) {
-+   return in_interrupt();
-+}
-+
-+/***********************************************************
-+ *
-+ * Atomic flags
-+ *
-+ ***********************************************************/
-+
-+VCOS_INLINE_IMPL
-+VCOS_STATUS_T vcos_atomic_flags_create(VCOS_ATOMIC_FLAGS_T *atomic_flags)
-+{
-+   atomic_set(atomic_flags, 0);
-+   return VCOS_SUCCESS;
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_atomic_flags_or(VCOS_ATOMIC_FLAGS_T *atomic_flags, uint32_t flags)
-+{
-+   uint32_t value;
-+   do {
-+      value = atomic_read(atomic_flags);
-+   } while (atomic_cmpxchg(atomic_flags, value, value | flags) != value);
-+}
-+
-+VCOS_INLINE_IMPL
-+uint32_t vcos_atomic_flags_get_and_clear(VCOS_ATOMIC_FLAGS_T *atomic_flags)
-+{
-+   return atomic_xchg(atomic_flags, 0);
-+}
-+
-+VCOS_INLINE_IMPL
-+void vcos_atomic_flags_delete(VCOS_ATOMIC_FLAGS_T *atomic_flags)
-+{
-+}
-+
-+#undef VCOS_ASSERT_LOGGING_DISABLE
-+#define VCOS_ASSERT_LOGGING_DISABLE 0
-+
-+#endif /* VCOS_INLINE_BODIES */
-+
-+VCOS_INLINE_DECL void _vcos_thread_sem_wait(void);
-+VCOS_INLINE_DECL void _vcos_thread_sem_post(VCOS_THREAD_T *);
-+
-+/***********************************************************
-+ *
-+ * Misc
-+ *
-+ ***********************************************************/
-+VCOS_INLINE_DECL char *vcos_strdup(const char *str);
-+
-+/***********************************************************
-+ *
-+ * Logging
-+ *
-+ ***********************************************************/
-+
-+VCOSPRE_ const char * VCOSPOST_ _vcos_log_level(void);
-+#define _VCOS_LOG_LEVEL() _vcos_log_level()
-+
-+#define  vcos_log_platform_init()               _vcos_log_platform_init()
-+#define  vcos_log_platform_register(category)   _vcos_log_platform_register(category)
-+#define  vcos_log_platform_unregister(category) _vcos_log_platform_unregister(category)
-+
-+struct VCOS_LOG_CAT_T;  /* Forward declaration since vcos_logging.h hasn't been included yet */
-+
-+void _vcos_log_platform_init(void);
-+void _vcos_log_platform_register(struct VCOS_LOG_CAT_T *category);
-+void _vcos_log_platform_unregister(struct VCOS_LOG_CAT_T *category);
-+
-+/***********************************************************
-+ *
-+ * Memory barriers
-+ *
-+ ***********************************************************/
-+
-+#define vcos_wmb(x) wmb()
-+#define vcos_rmb() rmb()
-+
-+#include "interface/vcos/generic/vcos_common.h"
-+/*#include "interface/vcos/generic/vcos_generic_quickslow_mutex.h" */
-+
-+#endif /* VCOS_PLATFORM_H */
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_platform_types.h
-@@ -0,0 +1,47 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  osal
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - platform-specific types and defines
-+=============================================================================*/
-+
-+#ifndef VCOS_PLATFORM_TYPES_H
-+#define VCOS_PLATFORM_TYPES_H
-+
-+#include <stddef.h>
-+#include <linux/types.h>
-+#include <linux/bug.h>
-+
-+#define VCOSPRE_ extern
-+#define VCOSPOST_
-+
-+#if defined(__GNUC__) && (( __GNUC__ > 2 ) || (( __GNUC__ == 2 ) && ( __GNUC_MINOR__ >= 3 )))
-+#define VCOS_FORMAT_ATTR_(ARCHETYPE, STRING_INDEX, FIRST_TO_CHECK)  __attribute__ ((format (ARCHETYPE, STRING_INDEX, FIRST_TO_CHECK)))
-+#else
-+#define VCOS_FORMAT_ATTR_(ARCHETYPE, STRING_INDEX, FIRST_TO_CHECK)
-+#endif
-+
-+#if !defined( __STDC_VERSION__ )
-+#define __STDC_VERSION__ 199901L
-+#endif
-+
-+#if !defined( __STDC_VERSION )
-+#define __STDC_VERSION   __STDC_VERSION__
-+#endif
-+
-+static inline void __vcos_bkpt( void ) { BUG(); }
-+#define VCOS_BKPT __vcos_bkpt()
-+
-+#define VCOS_ASSERT_MSG(...) printk( KERN_ERR "vcos_assert: " __VA_ARGS__ )
-+
-+#define PRId64 "lld"
-+#define PRIi64 "lli"
-+#define PRIo64 "llo"
-+#define PRIu64 "llu"
-+#define PRIx64 "llx"
-+
-+#endif
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_thread_map.c
-@@ -0,0 +1,129 @@
-+/*****************************************************************************
-+* Copyright 2009 - 2010 Broadcom Corporation.  All rights reserved.
-+*
-+* Unless you and Broadcom execute a separate written software license
-+* agreement governing use of this software, this software is licensed to you
-+* under the terms of the GNU General Public License version 2, available at
-+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-+*
-+* Notwithstanding the above, under no circumstances may you combine this
-+* software in any way with any other Broadcom software provided under a
-+* license other than the GPL, without Broadcom's express prior written
-+* consent.
-+*****************************************************************************/
-+
-+/** Support to allow VCOS thread-related functions to be called from
-+  * threads that were not created by VCOS.
-+  */
-+
-+#include <linux/semaphore.h>
-+#include <linux/vmalloc.h>
-+#include <linux/list.h>
-+#include <linux/sched.h>
-+
-+#include "vcos_thread_map.h"
-+#include "interface/vcos/vcos_logging.h"
-+
-+/*
-+ * Store the vcos_thread pointer at the end of
-+ * current kthread stack, right after the thread_info
-+ * structure.
-+ *
-+ * I belive we should be safe here to steal these 4 bytes
-+ * from the stack, as long as the vcos thread does not use up
-+ * all the stack available
-+ *
-+ * NOTE: This scheme will not work on architectures with stack growing up
-+ */
-+
-+/* Shout, if we are not being compiled for ARM kernel */
-+
-+#ifndef CONFIG_ARM
-+#error " **** The vcos kthread implementation may not work for non-ARM kernel ****"
-+#endif
-+
-+static inline void *to_current_vcos_thread(void)
-+{
-+   unsigned long *vcos_data;
-+
-+   vcos_data = (unsigned long *)((char *)current_thread_info() + sizeof(struct thread_info));
-+
-+   return (void *)vcos_data;
-+}
-+
-+
-+static inline void *to_vcos_thread(struct task_struct *tsk)
-+{
-+   unsigned long *vcos_data;
-+
-+   vcos_data = (unsigned long *)((char *)tsk->stack + sizeof(struct thread_info));
-+
-+   return (void *)vcos_data;
-+}
-+
-+/**
-+   @fn uint32_t vcos_add_thread(THREAD_MAP_T *vcos_thread);
-+*/
-+uint32_t vcos_add_thread(VCOS_THREAD_T *vcos_thread)
-+{
-+   VCOS_THREAD_T **vcos_thread_storage = (VCOS_THREAD_T **)to_current_vcos_thread();
-+
-+   *vcos_thread_storage = vcos_thread;
-+
-+   return(0);
-+}
-+
-+
-+/**
-+   @fn uint32_t vcos_remove_thread(struct task_struct * thread_id);
-+*/
-+uint32_t vcos_remove_thread(struct task_struct *thread_id)
-+{
-+   /* Remove thread_id -> VCOS_THREAD_T relationship */
-+   VCOS_THREAD_T **vcos_thread_storage;
-+
-+   /*
-+    * We want to be able to build vcos as a loadable module, which
-+    * means that we can't call get_task_struct. So we assert if we're
-+    * ever called with thread_id != current.
-+    */
-+
-+   BUG_ON( thread_id != current );
-+
-+   vcos_thread_storage = (VCOS_THREAD_T **)to_vcos_thread(thread_id);
-+
-+   *(unsigned long *)vcos_thread_storage = 0xCAFEBABE;
-+
-+   return(0);
-+}
-+
-+
-+VCOS_THREAD_T *vcos_kthread_current(void)
-+{
-+   VCOS_THREAD_T **vcos_thread_storage = (VCOS_THREAD_T **)to_current_vcos_thread();
-+
-+   /* If we find this, either the thread is already dead or stack pages of a
-+    * dead vcos thread are re-allocated to this one.
-+    *
-+    * Since there's no way to differentiate between these 2 cases, we just dump
-+    * the current task name to the log.
-+    *
-+    * If the current thread is created using VCOS API, you should *never* see this
-+    * print.
-+    * 
-+    * If its a non-VCOS thread, just let it go ...
-+    *
-+    * To debug VCOS, uncomment printk's under the "if" condition below
-+    *
-+    */
-+   if (*vcos_thread_storage == (void *)0xCAFEBABE)
-+   {
-+     #if 0
-+      printk(KERN_DEBUG"****************************************************\n");
-+      printk(KERN_DEBUG"%s : You have a problem, if \"%s\" is a VCOS thread\n",__func__, current->comm);
-+      printk(KERN_DEBUG"****************************************************\n");
-+     #endif
-+   }
-+
-+   return *vcos_thread_storage;
-+}
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_thread_map.h
-@@ -0,0 +1,39 @@
-+/*****************************************************************************
-+* Copyright 2009 - 2010 Broadcom Corporation.  All rights reserved.
-+*
-+* Unless you and Broadcom execute a separate written software license
-+* agreement governing use of this software, this software is licensed to you
-+* under the terms of the GNU General Public License version 2, available at
-+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-+*
-+* Notwithstanding the above, under no circumstances may you combine this
-+* software in any way with any other Broadcom software provided under a
-+* license other than the GPL, without Broadcom's express prior written
-+* consent.
-+*****************************************************************************/
-+
-+
-+#ifndef VCOS_THREAD_MAP_H
-+#define VCOS_THREAD_MAP_H
-+
-+#include <linux/string.h>
-+
-+#include "vcos_platform.h"
-+
-+static inline void vcos_thread_map_init(void)
-+{
-+   return;
-+}
-+
-+static inline void vcos_thread_map_cleanup(void)
-+{
-+   return;
-+}
-+
-+uint32_t vcos_add_thread(VCOS_THREAD_T *vcos_thread);
-+
-+uint32_t vcos_remove_thread(struct task_struct *thread_id);
-+
-+VCOS_THREAD_T *vcos_kthread_current(void);
-+
-+#endif /*VCOS_THREAD_MAP_H */
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos.h
-@@ -0,0 +1,201 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - public header file
-+=============================================================================*/
-+
-+/**
-+  * \mainpage OS Abstraction Layer
-+  *
-+  * \section intro Introduction
-+  *
-+  * This abstraction layer is here to allow the underlying OS to be easily changed (e.g. from
-+  * Nucleus to ThreadX) and to aid in porting host applications to new targets.
-+  *
-+  * \subsection error Error handling
-+  *
-+  * Wherever possible, VCOS functions assert internally and return void. The only exceptions
-+  * are creation functions (which might fail due to lack of resources) and functions that
-+  * might timeout or fail due to lack of space. Errors that might be reported by the underlying
-+  * OS API (e.g. invalid mutex) are treated as a programming error, and are merely asserted on.
-+  *
-+  * \section thread_synch Threads and synchronisation
-+  *
-+  * \subsection thread Threads
-+  *
-+  * The thread API is somewhat different to that found in Nucleus. In particular, threads
-+  * cannot just be destroyed at arbitrary times and nor can they merely exit. This is so
-+  * that the same API can be implemented across all interesting platforms without too much
-+  * difficulty. See vcos_thread.h for details. Thread attributes are configured via
-+  * the VCOS_THREAD_ATTR_T structure, found in vcos_thread_attr.h.
-+  *
-+  * \subsection sema Semaphores
-+  *
-+  * Counted semaphores (c.f. Nucleus NU_SEMAPHORE) are created with VCOS_SEMAPHORE_T.
-+  * Under ThreadX on VideoCore, semaphores are implemented using VideoCore spinlocks, and
-+  * so are quite a lot faster than ordinary ThreadX semaphores. See vcos_semaphore.h.
-+  *
-+  * \subsection mtx Mutexes
-+  *
-+  * Mutexes are used for locking. Attempts to take a mutex twice, or to unlock it
-+  * in a different thread to the one in which it was locked should be expected to fail.
-+  * Mutexes are not re-entrant (see vcos_reentrant_mutex.h for a slightly slower
-+  * re-entrant mutex).
-+  *
-+  * \subsection evflags Event flags
-+  *
-+  * Event flags (the ThreadX name - also known as event groups under Nucleus) provide
-+  * 32 flags which can be waited on by multiple clients, and signalled by multiple clients.
-+  * A timeout can be specified. See vcos_event_flags.h. An alternative to this is the
-+  * VCOS_EVENT_T (see vcos_event.h) which is akin to the Win32 auto-reset event, or a
-+  * saturating counted semaphore.
-+  *
-+  * \subsection event Events
-+  *
-+  * A VCOS_EVENT_T is a bit like a saturating semaphore. No matter how many times it
-+  * is signalled, the waiter will only wake up once. See vcos_event.h. You might think this
-+  * is useful if you suspect that the cost of reading the semaphore count (perhaps via a
-+  * system call) is expensive on your platform.
-+  *
-+  * \subsection tls Thread local storage
-+  *
-+  * Thread local storage is supported using vcos_tls.h. This is emulated on Nucleus
-+  * and ThreadX.
-+  *
-+  * \section int Interrupts
-+  *
-+  * The legacy LISR/HISR scheme found in Nucleus is supported via the legacy ISR API,
-+  * which is also supported on ThreadX. New code should avoid this, and old code should
-+  * be migrated away from it, since it is slow. See vcos_legacy_isr.h.
-+  *
-+  * Registering an interrupt handler, and disabling/restoring interrupts, is handled
-+  * using the functions in vcos_isr.h.
-+  *
-+  */
-+
-+/**
-+  * \file vcos.h
-+  *
-+  * This is the top level header file. Clients include this. It pulls in the platform-specific
-+  * header file (vcos_platform.h) together with header files defining the expected APIs, such
-+  * as vcos_mutex.h, vcos_semaphore.h, etc. It is also possible to include these header files
-+  * directly.
-+  *
-+  */
-+
-+#ifndef VCOS_H
-+#define VCOS_H
-+
-+#include "interface/vcos/vcos_assert.h"
-+#include "vcos_types.h"
-+#include "vcos_platform.h"
-+
-+#ifndef VCOS_INIT_H
-+#include "interface/vcos/vcos_init.h"
-+#endif
-+
-+#ifndef VCOS_SEMAPHORE_H
-+#include "interface/vcos/vcos_semaphore.h"
-+#endif
-+
-+#ifndef VCOS_THREAD_H
-+#include "interface/vcos/vcos_thread.h"
-+#endif
-+
-+#ifndef VCOS_MUTEX_H
-+#include "interface/vcos/vcos_mutex.h"
-+#endif
-+
-+#ifndef VCOS_MEM_H
-+#include "interface/vcos/vcos_mem.h"
-+#endif
-+
-+#ifndef VCOS_LOGGING_H
-+#include "interface/vcos/vcos_logging.h"
-+#endif
-+
-+#ifndef VCOS_STRING_H
-+#include "interface/vcos/vcos_string.h"
-+#endif
-+
-+#ifndef VCOS_EVENT_H
-+#include "interface/vcos/vcos_event.h"
-+#endif
-+
-+#ifndef VCOS_THREAD_ATTR_H
-+#include "interface/vcos/vcos_thread_attr.h"
-+#endif
-+
-+#ifndef VCOS_TLS_H
-+#include "interface/vcos/vcos_tls.h"
-+#endif
-+
-+#ifndef VCOS_REENTRANT_MUTEX_H
-+#include "interface/vcos/vcos_reentrant_mutex.h"
-+#endif
-+
-+#ifndef VCOS_NAMED_SEMAPHORE_H
-+#include "interface/vcos/vcos_named_semaphore.h"
-+#endif
-+
-+#ifndef VCOS_QUICKSLOW_MUTEX_H
-+#include "interface/vcos/vcos_quickslow_mutex.h"
-+#endif
-+
-+/* Headers with predicates */
-+
-+#if VCOS_HAVE_EVENT_FLAGS
-+#include "interface/vcos/vcos_event_flags.h"
-+#endif
-+
-+#if VCOS_HAVE_QUEUE
-+#include "interface/vcos/vcos_queue.h"
-+#endif
-+
-+#if VCOS_HAVE_LEGACY_ISR
-+#include "interface/vcos/vcos_legacy_isr.h"
-+#endif
-+
-+#if VCOS_HAVE_TIMER
-+#include "interface/vcos/vcos_timer.h"
-+#endif
-+
-+#if VCOS_HAVE_MEMPOOL
-+#include "interface/vcos/vcos_mempool.h"
-+#endif
-+
-+#if VCOS_HAVE_ISR
-+#include "interface/vcos/vcos_isr.h"
-+#endif
-+
-+#if VCOS_HAVE_ATOMIC_FLAGS
-+#include "interface/vcos/vcos_atomic_flags.h"
-+#endif
-+
-+#if VCOS_HAVE_ONCE
-+#include "interface/vcos/vcos_once.h"
-+#endif
-+
-+#if VCOS_HAVE_BLOCK_POOL
-+#include "interface/vcos/vcos_blockpool.h"
-+#endif
-+
-+#if VCOS_HAVE_FILE
-+#include "interface/vcos/vcos_file.h"
-+#endif
-+
-+#if VCOS_HAVE_CFG
-+#include "interface/vcos/vcos_cfg.h"
-+#endif
-+
-+#if VCOS_HAVE_CMD
-+#include "interface/vcos/vcos_cmd.h"
-+#endif
-+
-+#endif /* VCOS_H */
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_assert.h
-@@ -0,0 +1,269 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  osal
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - Assertion and error-handling macros.
-+=============================================================================*/
-+
-+
-+#ifndef VCOS_ASSERT_H
-+#define VCOS_ASSERT_H
-+
-+/*
-+ * Macro:
-+ *    vcos_assert(cond)
-+ *    vcos_assert_msg(cond, fmt, ...)
-+ * Use:
-+ *    Detecting programming errors by ensuring that assumptions are correct.
-+ * On failure:
-+ *    Performs a platform-dependent "breakpoint", usually with an assert-style
-+ *    message. The '_msg' variant expects a printf-style format string and
-+ *    parameters.
-+ *    If a failure is detected, the code should be fixed and rebuilt.
-+ * In release builds:
-+ *    Generates no code, i.e. does not evaluate 'cond'.
-+ * Returns:
-+ *    Nothing.
-+ *
-+ * Macro:
-+ *    vcos_demand(cond)
-+ *    vcos_demand_msg(cond, fmt, ...)
-+ * Use:
-+ *    Detecting fatal system errors that require a reboot.
-+ * On failure:
-+ *    Performs a platform-dependent "breakpoint", usually with an assert-style
-+ *    message, then calls vcos_abort (see below).
-+ * In release builds:
-+ *    Calls vcos_abort() if 'cond' is false.
-+ * Returns:
-+ *    Nothing (never, on failure).
-+ *
-+ * Macro:
-+ *    vcos_verify(cond)
-+ *    vcos_verify_msg(cond, fmt, ...)
-+ * Use:
-+ *    Detecting run-time errors and interesting conditions, normally within an
-+ *    'if' statement to catch the failures, i.e.
-+ *       if (!vcos_verify(cond)) handle_error();
-+ * On failure:
-+ *    Generates a message and optionally stops at a platform-dependent
-+ *    "breakpoint" (usually disabled). See vcos_verify_bkpts_enable below.
-+ * In release builds:
-+ *    Just evaluates and returns 'cond'.
-+ * Returns:
-+ *    Non-zero if 'cond' is true, otherwise zero.
-+ *
-+ * Macro:
-+ *    vcos_static_assert(cond)
-+ * Use:
-+ *    Detecting compile-time errors.
-+ * On failure:
-+ *    Generates a compiler error.
-+ * In release builds:
-+ *    Generates a compiler error.
-+ *
-+ * Function:
-+ *    void vcos_abort(void)
-+ * Use:
-+ *    Invokes the fatal error handling mechanism, alerting the host where
-+ *    applicable.
-+ * Returns:
-+ *    Never.
-+ *
-+ * Macro:
-+ *    VCOS_VERIFY_BKPTS
-+ * Use:
-+ *    Define in a module (before including vcos.h) to specify an alternative
-+ *    flag to control breakpoints on vcos_verify() failures.
-+ * Returns:
-+ *    Non-zero values enable breakpoints.
-+ *
-+ * Function:
-+ *    int vcos_verify_bkpts_enable(int enable);
-+ * Use:
-+ *    Sets the global flag controlling breakpoints on vcos_verify failures,
-+ *    enabling the breakpoints iff 'enable' is non-zero.
-+ * Returns:
-+ *    The previous state of the flag.
-+ *
-+ * Function:
-+ *    int vcos_verify_bkpts_enabled(void);
-+ * Use:
-+ *    Queries the state of the global flag enabling breakpoints on vcos_verify
-+ *    failures.
-+ * Returns:
-+ *    The current state of the flag.
-+ *
-+ * Examples:
-+ *
-+ * int my_breakpoint_enable_flag = 1;
-+ *
-+ * #define VCOS_VERIFY_BKPTS my_breakpoint_enable_flag
-+ *
-+ * #include "interface/vcos/vcos.h"
-+ *
-+ * vcos_static_assert((sizeof(object) % 32) == 0);
-+ *
-+ * // ...
-+ *
-+ *    vcos_assert_msg(postcondition_is_true, "Coding error");
-+ *
-+ *    if (!vcos_verify_msg(buf, "Buffer allocation failed (%d bytes)", size))
-+ *    {
-+ *       // Tidy up
-+ *       // ...
-+ *       return OUT_OF_MEMORY;
-+ *    }
-+ *
-+ *    vcos_demand(*p++==GUARDWORDHEAP);
-+ */
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+
-+#ifdef __COVERITY__
-+#undef VCOS_ASSERT_BKPT
-+#define VCOS_ASSERT_BKPT __coverity_panic__()
-+#endif
-+
-+#ifndef VCOS_VERIFY_BKPTS
-+#define VCOS_VERIFY_BKPTS vcos_verify_bkpts_enabled()
-+#endif
-+
-+#ifndef VCOS_BKPT
-+#if defined(__VIDEOCORE__) && !defined(VCOS_ASSERT_NO_BKPTS)
-+#define VCOS_BKPT _bkpt()
-+#else
-+#define VCOS_BKPT (void )0
-+#endif
-+#endif
-+
-+#ifndef VCOS_ASSERT_BKPT
-+#define VCOS_ASSERT_BKPT VCOS_BKPT
-+#endif
-+
-+#ifndef VCOS_VERIFY_BKPT
-+#define VCOS_VERIFY_BKPT (VCOS_VERIFY_BKPTS ? VCOS_BKPT : (void)0)
-+#endif
-+
-+VCOSPRE_ int VCOSPOST_ vcos_verify_bkpts_enabled(void);
-+VCOSPRE_ int VCOSPOST_ vcos_verify_bkpts_enable(int enable);
-+VCOSPRE_ void VCOSPOST_ vcos_abort(void);
-+
-+#ifndef VCOS_ASSERT_MSG
-+#ifdef LOGGING
-+extern void logging_assert(const char *file, const char *func, int line, const char *format, ...);
-+#define VCOS_ASSERT_MSG(...) ((VCOS_ASSERT_LOGGING && !VCOS_ASSERT_LOGGING_DISABLE) ? logging_assert(__FILE__, __func__, __LINE__, __VA_ARGS__) : (void)0)
-+#else
-+#define VCOS_ASSERT_MSG(...) ((void)0)
-+#endif
-+#endif
-+
-+#ifndef VCOS_VERIFY_MSG
-+#define VCOS_VERIFY_MSG(...) VCOS_ASSERT_MSG(__VA_ARGS__)
-+#endif
-+
-+#ifndef VCOS_ASSERT_LOGGING
-+#define VCOS_ASSERT_LOGGING 0
-+#endif
-+
-+#ifndef VCOS_ASSERT_LOGGING_DISABLE
-+#define VCOS_ASSERT_LOGGING_DISABLE 0
-+#endif
-+
-+#if !defined(NDEBUG) || defined(VCOS_RELEASE_ASSERTS)
-+
-+#ifndef vcos_assert
-+#define vcos_assert(cond) \
-+   ( (cond) ? (void)0 : (VCOS_ASSERT_MSG("%s", #cond), VCOS_ASSERT_BKPT) )
-+#endif
-+
-+#ifndef vcos_assert_msg
-+#define vcos_assert_msg(cond, ...) \
-+   ( (cond) ? (void)0 : (VCOS_ASSERT_MSG(__VA_ARGS__), VCOS_ASSERT_BKPT) )
-+#endif
-+
-+#else  /* !defined(NDEBUG) || defined(VCOS_RELEASE_ASSERTS) */
-+
-+#ifndef vcos_assert
-+#define vcos_assert(cond) (void)0
-+#endif
-+
-+#ifndef vcos_assert_msg
-+#define vcos_assert_msg(cond, ...) (void)0
-+#endif
-+
-+#endif /* !defined(NDEBUG) || defined(VCOS_RELEASE_ASSERTS) */
-+
-+#if !defined(NDEBUG)
-+
-+#ifndef vcos_demand
-+#define vcos_demand(cond) \
-+   ( (cond) ? (void)0 : (VCOS_ASSERT_MSG("%s", #cond), VCOS_ASSERT_BKPT, vcos_abort()) )
-+#endif
-+
-+#ifndef vcos_demand_msg
-+#define vcos_demand_msg(cond, ...) \
-+   ( (cond) ? (void)0 : (VCOS_ASSERT_MSG(__VA_ARGS__), VCOS_ASSERT_BKPT, vcos_abort()) )
-+#endif
-+
-+#ifndef vcos_verify
-+#define vcos_verify(cond) \
-+   ( (cond) ? 1 : (VCOS_VERIFY_MSG("%s", #cond), VCOS_VERIFY_BKPT, 0) )
-+#endif
-+
-+#ifndef vcos_verify_msg
-+#define vcos_verify_msg(cond, ...) \
-+   ( (cond) ? 1 : (VCOS_VERIFY_MSG(__VA_ARGS__), VCOS_VERIFY_BKPT, 0) )
-+#endif
-+
-+#else  /* !defined(NDEBUG) */
-+
-+#ifndef vcos_demand
-+#define vcos_demand(cond) \
-+   ( (cond) ? (void)0 : vcos_abort() )
-+#endif
-+
-+#ifndef vcos_demand_msg
-+#define vcos_demand_msg(cond, ...) \
-+   ( (cond) ? (void)0 : vcos_abort() )
-+#endif
-+
-+#ifndef vcos_verify
-+#define vcos_verify(cond) (cond)
-+#endif
-+
-+#ifndef vcos_verify_msg
-+#define vcos_verify_msg(cond, ...) (cond)
-+#endif
-+
-+#endif /* !defined(NDEBUG) */
-+
-+#ifndef vcos_static_assert
-+#if defined(__GNUC__)
-+#define vcos_static_assert(cond) __attribute__((unused)) extern int vcos_static_assert[(cond)?1:-1]
-+#else
-+#define vcos_static_assert(cond) extern int vcos_static_assert[(cond)?1:-1]
-+#endif
-+#endif
-+
-+#ifndef vc_assert
-+#define vc_assert(cond) vcos_assert(cond)
-+#endif
-+
-+/** Print out a backtrace, on supported platforms.
-+  */
-+extern void vcos_backtrace_self(void);
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif /* VCOS_ASSERT_H */
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_atomic_flags.h
-@@ -0,0 +1,72 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver (just for consistency with the rest of vcos ;)
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - public header file
-+=============================================================================*/
-+
-+#ifndef VCOS_ATOMIC_FLAGS_H
-+#define VCOS_ATOMIC_FLAGS_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+#include "vcos_platform.h"
-+
-+/**
-+ * \file vcos_atomic_flags.h
-+ *
-+ * Defines atomic flags API.
-+ *
-+ * 32 flags. Atomic "or" and "get and clear" operations
-+ */
-+
-+/**
-+ * Create an atomic flags instance.
-+ *
-+ * @param atomic_flags Pointer to atomic flags instance, filled in on return
-+ *
-+ * @return VCOS_SUCCESS if succeeded.
-+ */
-+VCOS_INLINE_DECL
-+VCOS_STATUS_T vcos_atomic_flags_create(VCOS_ATOMIC_FLAGS_T *atomic_flags);
-+
-+/**
-+ * Atomically set the specified flags.
-+ *
-+ * @param atomic_flags Instance to set flags on
-+ * @param flags        Mask of flags to set
-+ */
-+VCOS_INLINE_DECL
-+void vcos_atomic_flags_or(VCOS_ATOMIC_FLAGS_T *atomic_flags, uint32_t flags);
-+
-+/**
-+ * Retrieve the current flags and then clear them. The entire operation is
-+ * atomic.
-+ *
-+ * @param atomic_flags Instance to get/clear flags from/on
-+ *
-+ * @return Mask of flags which were set (and we cleared)
-+ */
-+VCOS_INLINE_DECL
-+uint32_t vcos_atomic_flags_get_and_clear(VCOS_ATOMIC_FLAGS_T *atomic_flags);
-+
-+/**
-+ * Delete an atomic flags instance.
-+ *
-+ * @param atomic_flags Instance to delete
-+ */
-+VCOS_INLINE_DECL
-+void vcos_atomic_flags_delete(VCOS_ATOMIC_FLAGS_T *atomic_flags);
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_build_info.h
-@@ -0,0 +1,5 @@
-+const char *vcos_get_build_hostname( void );
-+const char *vcos_get_build_version( void );
-+const char *vcos_get_build_time( void );
-+const char *vcos_get_build_date( void );
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_cfg.h
-@@ -0,0 +1,113 @@
-+/*****************************************************************************
-+* Copyright 2009 - 2011 Broadcom Corporation.  All rights reserved.
-+*
-+* Unless you and Broadcom execute a separate written software license
-+* agreement governing use of this software, this software is licensed to you
-+* under the terms of the GNU General Public License version 2, available at
-+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-+*
-+* Notwithstanding the above, under no circumstances may you combine this
-+* software in any way with any other Broadcom software provided under a
-+* license other than the GPL, without Broadcom's express prior written
-+* consent.
-+*****************************************************************************/
-+
-+#if !defined( VCOS_CFG_H )
-+#define VCOS_CFG_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+#include "vcos_platform.h"
-+
-+typedef struct opaque_vcos_cfg_buf_t    *VCOS_CFG_BUF_T;
-+typedef struct opaque_vcos_cfg_entry_t  *VCOS_CFG_ENTRY_T;
-+
-+/** \file vcos_file.h
-+  *
-+  * API for accessing configuration/statistics information. This
-+  * is loosely modelled on the linux proc entries.
-+  */
-+
-+typedef void (*VCOS_CFG_SHOW_FPTR)( VCOS_CFG_BUF_T buf, void *data );
-+typedef void (*VCOS_CFG_PARSE_FPTR)( VCOS_CFG_BUF_T buf, void *data );
-+
-+/** Create a configuration directory.
-+  *
-+  * @param entry        Place to store the created config entry.
-+  * @param parent       Parent entry (for directory like config 
-+  *                     options).
-+  * @param entryName    Name of the directory.
-+  */
-+
-+VCOS_STATUS_T vcos_cfg_mkdir( VCOS_CFG_ENTRY_T *entry,
-+                              VCOS_CFG_ENTRY_T *parent,
-+                              const char *dirName );           
-+
-+/** Create a configuration entry.
-+  *
-+  * @param entry        Place to store the created config entry.
-+  * @param parent       Parent entry (for directory like config 
-+  *                     options).
-+  * @param entryName    Name of the configuration entry.
-+  * @param showFunc     Function pointer to show configuration 
-+  *                     data.
-+  * @param parseFunc    Function pointer to parse new data. 
-+  */
-+
-+VCOS_STATUS_T vcos_cfg_create_entry( VCOS_CFG_ENTRY_T *entry,
-+                                     VCOS_CFG_ENTRY_T *parent,
-+                                     const char *entryName,
-+                                     VCOS_CFG_SHOW_FPTR showFunc,
-+                                     VCOS_CFG_PARSE_FPTR parseFunc,
-+                                     void *data );
-+
-+/** Determines if a configuration entry has been created or not.
-+  *
-+  * @param entry        Configuration entry to query.
-+  */
-+
-+int vcos_cfg_is_entry_created( VCOS_CFG_ENTRY_T entry );
-+
-+/** Returns the name of a configuration entry.
-+  *
-+  * @param entry        Configuration entry to query.
-+  */
-+
-+const char *vcos_cfg_get_entry_name( VCOS_CFG_ENTRY_T entry );
-+
-+/** Removes a configuration entry.
-+  *
-+  * @param entry        Configuration entry to remove.
-+  */
-+
-+VCOS_STATUS_T vcos_cfg_remove_entry( VCOS_CFG_ENTRY_T *entry );
-+
-+
-+/** Writes data into a configuration buffer. Only valid inside
-+  * the show function. 
-+  *
-+  * @param buf      Buffer to write data into.
-+  * @param fmt      printf style format string. 
-+  */
-+
-+void vcos_cfg_buf_printf( VCOS_CFG_BUF_T buf, const char *fmt, ... );
-+
-+/** Retrieves a null terminated string of the data associated
-+  * with the buffer. Only valid inside the parse function.
-+  *
-+  * @param buf      Buffer to get data from.
-+  * @param fmt      printf style format string. 
-+  */
-+
-+char *vcos_cfg_buf_get_str( VCOS_CFG_BUF_T buf );
-+
-+void *vcos_cfg_get_proc_entry( VCOS_CFG_ENTRY_T entry );
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_cmd.h
-@@ -0,0 +1,98 @@
-+/*****************************************************************************
-+* Copyright 2009 - 2011 Broadcom Corporation.  All rights reserved.
-+*
-+* Unless you and Broadcom execute a separate written software license
-+* agreement governing use of this software, this software is licensed to you
-+* under the terms of the GNU General Public License version 2, available at
-+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-+*
-+* Notwithstanding the above, under no circumstances may you combine this
-+* software in any way with any other Broadcom software provided under a
-+* license other than the GPL, without Broadcom's express prior written
-+* consent.
-+*****************************************************************************/
-+
-+#if !defined( VCOS_CMD_H )
-+#define VCOS_CMD_H
-+
-+/* ---- Include Files ----------------------------------------------------- */
-+
-+#include "interface/vcos/vcos.h"
-+#include "interface/vcos/vcos_stdint.h"
-+
-+
-+/* ---- Constants and Types ---------------------------------------------- */
-+
-+struct VCOS_CMD_S;
-+typedef struct VCOS_CMD_S VCOS_CMD_T;
-+
-+typedef struct
-+{
-+    int         argc;           /* Number of arguments (includes the command/sub-command) */
-+    char      **argv;           /* Array of arguments */
-+    char      **argv_orig;      /* Original array of arguments */
-+
-+    VCOS_CMD_T *cmd_entry;
-+    VCOS_CMD_T *cmd_parent_entry;
-+
-+    int         use_log;        /* Output being logged? */
-+    size_t      result_size;    /* Size of result buffer. */
-+    char       *result_ptr;     /* Next place to put output. */
-+    char       *result_buf;     /* Start of the buffer. */
-+
-+} VCOS_CMD_PARAM_T;
-+
-+typedef VCOS_STATUS_T (*VCOS_CMD_FUNC_T)( VCOS_CMD_PARAM_T *param );
-+
-+struct VCOS_CMD_S
-+{
-+    const char         *name;
-+    const char         *args;
-+    VCOS_CMD_FUNC_T     cmd_fn;
-+    VCOS_CMD_T         *sub_cmd_entry;
-+    const char         *descr;
-+
-+};
-+
-+/* ---- Variable Externs ------------------------------------------------- */
-+
-+/* ---- Function Prototypes ---------------------------------------------- */
-+
-+/*
-+ * Common printing routine for generating command output.
-+ */
-+VCOSPRE_ void VCOSPOST_ vcos_cmd_error( VCOS_CMD_PARAM_T *param, const char *fmt, ... ) VCOS_FORMAT_ATTR_(printf, 2, 3);
-+VCOSPRE_ void VCOSPOST_ vcos_cmd_printf( VCOS_CMD_PARAM_T *param, const char *fmt, ... ) VCOS_FORMAT_ATTR_(printf, 2, 3);
-+VCOSPRE_ void VCOSPOST_ vcos_cmd_vprintf( VCOS_CMD_PARAM_T *param, const char *fmt, va_list args ) VCOS_FORMAT_ATTR_(printf, 2, 0);
-+
-+/*
-+ * Cause vcos_cmd_error, printf and vprintf to always log to the provided
-+ * category. When this call is made, the results buffer passed into
-+ * vcos_cmd_execute is used as a line buffer and does not need to be
-+ * output by the caller.
-+ */
-+VCOSPRE_ void VCOSPOST_ vcos_cmd_always_log_output( VCOS_LOG_CAT_T *log_category );
-+
-+/*
-+ * Prints command usage for the current command.
-+ */
-+VCOSPRE_ void VCOSPOST_ vcos_cmd_usage( VCOS_CMD_PARAM_T *param );
-+
-+/*
-+ * Register commands to be processed
-+ */
-+VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_cmd_register( VCOS_CMD_T *cmd_entry );
-+
-+/*
-+ * Registers multiple commands to be processed. The array should
-+ * be terminated by an entry with all zeros.
-+ */
-+VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_cmd_register_multiple( VCOS_CMD_T *cmd_entry );
-+
-+/*
-+ * Executes a command based on a command line.
-+ */
-+VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_cmd_execute( int argc, char **argv, size_t result_size, char *result_buf );
-+
-+#endif /* VCOS_CMD_H */
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_ctype.h
-@@ -0,0 +1,29 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - public header file
-+=============================================================================*/
-+
-+#ifndef VCOS_CTYPE_H
-+#define VCOS_CTYPE_H
-+
-+/**
-+  * \file
-+  *
-+  * ctype functions.
-+  *
-+  */
-+
-+#ifdef __KERNEL__
-+#include <linux/ctype.h>
-+#else
-+#include <ctype.h>
-+#endif
-+
-+#endif
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_dlfcn.h
-@@ -0,0 +1,69 @@
-+/*=============================================================================
-+Copyright (c) 2010 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VCOS - abstraction over dynamic library opening
-+=============================================================================*/
-+
-+#ifndef VCOS_DLFCN_H
-+#define VCOS_DLFCN_H
-+
-+#include "interface/vcos/vcos_types.h"
-+#include "vcos_platform.h"
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#define VCOS_DL_LAZY 1
-+#define VCOS_DL_NOW  2
-+
-+/**
-+ * \file
-+ *
-+ * Loading dynamic libraries. See also dlfcn.h.
-+ */
-+
-+/** Open a dynamic library.
-+  *
-+  * @param name  name of the library
-+  * @param mode  Load lazily or immediately (VCOS_DL_LAZY, VCOS_DL_NOW).
-+  *
-+  * @return A handle for use in subsequent calls.
-+  */
-+VCOSPRE_ void * VCOSPOST_ vcos_dlopen(const char *name, int mode);
-+
-+/** Look up a symbol.
-+  *
-+  * @param handle Handle to open
-+  * @param name   Name of function
-+  *
-+  * @return Function pointer, or NULL.
-+  */
-+VCOSPRE_ void VCOSPOST_ (*vcos_dlsym(void *handle, const char *name))(void);
-+
-+/** Close a library
-+  *
-+  * @param handle Handle to close
-+  */
-+VCOSPRE_ int VCOSPOST_ vcos_dlclose (void *handle);
-+
-+/** Return error message from library.
-+  *
-+  * @param err  On return, set to non-zero if an error has occurred
-+  * @param buf  Buffer to write error to
-+  * @param len  Size of buffer (including terminating NUL).
-+  */
-+VCOSPRE_ int VCOSPOST_ vcos_dlerror(int *err, char *buf, size_t buflen);
-+
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif
-+
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_event.h
-@@ -0,0 +1,97 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - public header file for events
-+=============================================================================*/
-+
-+#ifndef VCOS_EVENT_H
-+#define VCOS_EVENT_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+#include "vcos_platform.h"
-+
-+/** 
-+  * \file
-+  *
-+  * An event is akin to the Win32 auto-reset event.
-+  *
-+  *
-+  * Signalling an event will wake up one waiting thread only. Once one
-+  * thread has been woken the event atomically returns to the unsignalled
-+  * state.
-+  * 
-+  * If no threads are waiting on the event when it is signalled it remains
-+  * signalled.
-+  *
-+  * This is almost, but not quite, completely unlike the "event flags"
-+  * object based on Nucleus event groups and ThreadX event flags.
-+  *
-+  * In particular, it should be similar in speed to a semaphore, unlike
-+  * the event flags.
-+  */
-+
-+/**
-+  * Create an event instance.
-+  *
-+  * @param event  Filled in with constructed event.
-+  * @param name   Name of the event (for debugging)
-+  *
-+  * @return VCOS_SUCCESS on success, or error code.
-+  */
-+VCOS_INLINE_DECL
-+VCOS_STATUS_T vcos_event_create(VCOS_EVENT_T *event, const char *name);
-+
-+#ifndef vcos_event_signal
-+
-+/**
-+  * Signal the event. The event will return to being unsignalled
-+  * after exactly one waiting thread has been woken up. If no
-+  * threads are waiting it remains signalled.
-+  *
-+  * @param event The event to signal
-+  */
-+VCOS_INLINE_DECL
-+void vcos_event_signal(VCOS_EVENT_T *event);
-+
-+/**
-+  * Wait for the event.
-+  *
-+  * @param event The event to wait for
-+  * @return VCOS_SUCCESS on success, VCOS_EAGAIN if the wait was interrupted.
-+  */
-+VCOS_INLINE_DECL
-+VCOS_STATUS_T vcos_event_wait(VCOS_EVENT_T *event);
-+
-+/**
-+  * Try event, but don't block.
-+  *
-+  * @param event The event to try
-+  * @return VCOS_SUCCESS on success, VCOS_EAGAIN if the event is not currently signalled
-+  */
-+VCOS_INLINE_DECL
-+VCOS_STATUS_T vcos_event_try(VCOS_EVENT_T *event);
-+
-+#endif
-+
-+/*
-+ * Destroy an event.
-+ */
-+VCOS_INLINE_DECL
-+void vcos_event_delete(VCOS_EVENT_T *event);
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif
-+
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_event_flags.h
-@@ -0,0 +1,98 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - public header file
-+=============================================================================*/
-+
-+#ifndef VCOS_EVENT_FLAGS_H
-+#define VCOS_EVENT_FLAGS_H
-+
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+#include "vcos_platform.h"
-+
-+#define VCOS_EVENT_FLAGS_SUSPEND    VCOS_SUSPEND
-+#define VCOS_EVENT_FLAGS_NO_SUSPEND VCOS_NO_SUSPEND
-+typedef VCOS_OPTION VCOS_EVENTGROUP_OPERATION_T;
-+
-+/**
-+ * \file vcos_event_flags.h
-+ *
-+ * Defines event flags API.
-+ *
-+ * Similar to Nucleus event groups.
-+ *
-+ * These have the same semantics as Nucleus event groups and ThreadX event
-+ * flags. As such, they are quite complex internally; if speed is important
-+ * they might not be your best choice.
-+ *
-+ */
-+
-+/**
-+ * Create an event flags instance.
-+ *
-+ * @param flags   Pointer to event flags instance, filled in on return.
-+ * @param name    Name for the event flags, used for debug.
-+ *
-+ * @return VCOS_SUCCESS if succeeded.
-+ */
-+
-+VCOS_INLINE_DECL
-+VCOS_STATUS_T vcos_event_flags_create(VCOS_EVENT_FLAGS_T *flags, const char *name);
-+
-+/**
-+  * Set some events.
-+  *
-+  * @param flags   Instance to set flags on
-+  * @param events  Bitmask of the flags to actually set
-+  * @param op      How the flags should be set. VCOS_OR will OR in the flags; VCOS_AND
-+  *                will AND them in, possibly clearing existing flags.
-+  */
-+VCOS_INLINE_DECL
-+void vcos_event_flags_set(VCOS_EVENT_FLAGS_T *flags,
-+                          VCOS_UNSIGNED events,
-+                          VCOS_OPTION op);
-+
-+/**
-+ * Retrieve some events.
-+ *
-+ * Waits until the specified events have been set.
-+ *
-+ * @param flags            Instance to wait on
-+ * @param requested_events The bitmask to wait for
-+ * @param op               VCOS_OR - get any; VCOS_AND - get all.
-+ * @param ms_suspend       How long to wait, in milliseconds
-+ * @param retrieved_events the events actually retrieved.
-+ *
-+ * @return VCOS_SUCCESS if events were retrieved. VCOS_EAGAIN if the
-+ * timeout expired.
-+ */
-+VCOS_INLINE_DECL
-+VCOS_STATUS_T vcos_event_flags_get(VCOS_EVENT_FLAGS_T *flags,
-+                                                     VCOS_UNSIGNED requested_events,
-+                                                     VCOS_OPTION op,
-+                                                     VCOS_UNSIGNED ms_suspend,
-+                                                     VCOS_UNSIGNED *retrieved_events);
-+
-+
-+/**
-+ * Delete an event flags instance.
-+ */
-+VCOS_INLINE_DECL
-+void vcos_event_flags_delete(VCOS_EVENT_FLAGS_T *);
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_init.h
-@@ -0,0 +1,43 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - initialization routines
-+=============================================================================*/
-+
-+
-+#include "interface/vcos/vcos_types.h"
-+#include "vcos_platform.h"
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+/** \file
-+  *
-+  * Some OS support libraries need some initialization. To support this, call this
-+  * function at the start of day.
-+  */
-+
-+VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_init(void);
-+VCOSPRE_ void VCOSPOST_ vcos_deinit(void);
-+VCOSPRE_ void VCOSPOST_ vcos_global_lock(void);
-+VCOSPRE_ void VCOSPOST_ vcos_global_unlock(void);
-+
-+/** Pass in the argv/argc arguments passed to main() */
-+VCOSPRE_ void VCOSPOST_ vcos_set_args(int argc, const char **argv);
-+
-+/** Return argc. */
-+VCOSPRE_ int VCOSPOST_ vcos_get_argc(void);
-+
-+/** Return argv. */
-+VCOSPRE_ const char ** VCOSPOST_ vcos_get_argv(void);
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_logging.h
-@@ -0,0 +1,279 @@
-+/*=============================================================================
-+Copyright (c) 2009-2011 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - logging support
-+=============================================================================*/
-+
-+#ifndef VCOS_LOGGING_H
-+#define VCOS_LOGGING_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include <stdarg.h>
-+
-+#include "interface/vcos/vcos_types.h"
-+#include "vcos_platform.h"
-+
-+/**
-+ * \file
-+ *
-+ * Logging support
-+ *
-+ * This provides categorised logging. Clients register
-+ * a category, and then get a number of logging levels for
-+ * that category.
-+ *
-+ * The logging level flag is tested using a flag *before* the
-+ * function call, which makes logging very fast when disabled - there
-+ * is no function call overhead just to find out that this log
-+ * message is disabled.
-+ *
-+ * \section VCOS_LOG_CATEGORY
-+ *
-+ * As a convenience, clients define VCOS_LOG_CATEGORY to point to
-+ * their category; the various vcos_log_xxx() macros then expand to
-+ * use this.
-+ *
-+ * e.g.
-+ *
-+ *     #define VCOS_LOG_CATEGORY (&my_category)
-+ *
-+ *     #include <interface/vcos/vcos.h>
-+ *
-+ *     VCOS_LOG_CAT_T my_category;
-+ *
-+ *     ....
-+ *
-+ *     vcos_log_trace("Stuff happened: %d", n_stuff);
-+ *
-+ */
-+
-+/** Logging levels */
-+typedef enum VCOS_LOG_LEVEL_T
-+{
-+   VCOS_LOG_UNINITIALIZED   = 0,
-+   VCOS_LOG_NEVER,
-+   VCOS_LOG_ERROR,
-+   VCOS_LOG_WARN,
-+   VCOS_LOG_INFO,
-+   VCOS_LOG_TRACE,
-+} VCOS_LOG_LEVEL_T;
-+
-+
-+/** Initialize a logging category without going through vcos_log_register().
-+ *
-+ * This is useful for the case where there is no obvious point to do the
-+ * registration (no initialization function for the module). However, it
-+ * means that your logging category is not registered, so cannot be easily
-+ * changed at run-time.
-+ */
-+#define VCOS_LOG_INIT(n,l) { l, n, 0, {0}, 0, 0 }
-+
-+/** A registered logging category.
-+  */
-+typedef struct VCOS_LOG_CAT_T
-+{
-+   VCOS_LOG_LEVEL_T level;      /** Which levels are enabled for this category */
-+   const char *name;            /** Name for this category. */
-+   struct VCOS_LOG_CAT_T *next;
-+   struct {
-+      unsigned int want_prefix:1;
-+   } flags;
-+   unsigned int refcount;
-+   void *platform_data;         /** platform specific data */
-+} VCOS_LOG_CAT_T;
-+
-+typedef void (*VCOS_VLOG_IMPL_FUNC_T)(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, va_list args);
-+
-+/** Convert a VCOS_LOG_LEVEL_T into a printable string.
-+  * The platform needs to implement this function.
-+  */
-+VCOSPRE_ const char * VCOSPOST_ vcos_log_level_to_string( VCOS_LOG_LEVEL_T level );
-+
-+/** Convert a string into a VCOS_LOG_LEVEL_T
-+  * The platform needs to implement this function.
-+  */
-+VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_string_to_log_level( const char *str, VCOS_LOG_LEVEL_T *level );
-+
-+/** Log a message. Basic API. Normal code should not use this.
-+  * The platform needs to implement this function.
-+  */
-+VCOSPRE_ void VCOSPOST_ vcos_log_impl(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, ...) VCOS_FORMAT_ATTR_(printf, 3, 4);
-+
-+/** Log a message using a varargs parameter list. Normal code should
-+  * not use this.
-+  */
-+VCOSPRE_ void VCOSPOST_ vcos_vlog_impl(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, va_list args) VCOS_FORMAT_ATTR_(printf, 3, 0);
-+
-+/** Set the function which does the actual logging output.
-+ *  Passing in NULL causes the default logging function to be
-+ *  used.
-+  */
-+VCOSPRE_ void VCOSPOST_ vcos_set_vlog_impl( VCOS_VLOG_IMPL_FUNC_T vlog_impl_func );
-+
-+/** The default logging function, which is provided by each
-+  * platform.
-+  */
-+
-+VCOSPRE_ void VCOSPOST_ vcos_vlog_default_impl(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, va_list args) VCOS_FORMAT_ATTR_(printf, 3, 0);
-+
-+/*
-+ * Initialise the logging subsystem. This is called from
-+ * vcos_init() so you don't normally need to call it.
-+ */
-+VCOSPRE_ void VCOSPOST_ vcos_logging_init(void);
-+
-+/** Register a logging category.
-+  *
-+  * @param name the name of this category.
-+  * @param category the category to register.
-+  */
-+VCOSPRE_ void VCOSPOST_ vcos_log_register(const char *name, VCOS_LOG_CAT_T *category);
-+
-+/** Unregister a logging category.
-+  */
-+VCOSPRE_ void VCOSPOST_ vcos_log_unregister(VCOS_LOG_CAT_T *category);
-+
-+/** Return a default logging category, for people too lazy to create their own.
-+  *
-+  * Using the default category will be slow (there's an extra function
-+  * call overhead). Don't do this in normal code.
-+  */
-+VCOSPRE_ const VCOS_LOG_CAT_T * VCOSPOST_ vcos_log_get_default_category(void);
-+
-+VCOSPRE_ void VCOSPOST_ vcos_set_log_options(const char *opt);
-+
-+/** Set the logging level for a category at run time. Without this, the level
-+  * will be that set by vcos_log_register from a platform-specific source.
-+  *
-+  * @param category the category to modify.
-+  * @param level the new logging level for this category.
-+  */
-+VCOS_STATIC_INLINE void vcos_log_set_level(VCOS_LOG_CAT_T *category, VCOS_LOG_LEVEL_T level)
-+{
-+   category->level = level;
-+}
-+
-+#define vcos_log_dump_mem(cat,label,addr,voidMem,numBytes)  do { if (vcos_is_log_enabled(cat,VCOS_LOG_TRACE)) vcos_log_dump_mem_impl(cat,label,addr,voidMem,numBytes); } while (0)
-+
-+void vcos_log_dump_mem_impl( const VCOS_LOG_CAT_T *cat,
-+                             const char           *label,
-+                             uint32_t              addr,
-+                             const void           *voidMem,
-+                             size_t                numBytes );
-+
-+/*
-+ * Platform specific hooks (optional).
-+ */
-+#ifndef vcos_log_platform_init
-+#define vcos_log_platform_init()                (void)0
-+#endif
-+
-+#ifndef vcos_log_platform_register
-+#define vcos_log_platform_register(category)    (void)0
-+#endif
-+
-+#ifndef vcos_log_platform_unregister
-+#define vcos_log_platform_unregister(category)  (void)0
-+#endif
-+
-+/* VCOS_TRACE() - deprecated macro which just outputs in a debug build and
-+ * is a no-op in a release build.
-+ *
-+ * _VCOS_LOG_X() - internal macro which outputs if the current level for the
-+ * particular category is higher than the supplied message level.
-+ */
-+
-+#define VCOS_LOG_DFLT_CATEGORY vcos_log_get_default_category()
-+
-+#define _VCOS_LEVEL(x) (x)
-+
-+#define vcos_is_log_enabled(cat,_level)  (_VCOS_LEVEL((cat)->level) >= _VCOS_LEVEL(_level))
-+
-+#if defined(_VCOS_METAWARE) || defined(__GNUC__)
-+
-+# if !defined(NDEBUG) || defined(VCOS_ALWAYS_WANT_LOGGING)
-+#  define VCOS_LOGGING_ENABLED
-+#  define _VCOS_LOG_X(cat, _level, fmt...)   do { if (vcos_is_log_enabled(cat,_level)) vcos_log_impl(cat,_level,fmt); } while (0)
-+#  define _VCOS_VLOG_X(cat, _level, fmt, ap) do { if (vcos_is_log_enabled(cat,_level)) vcos_vlog_impl(cat,_level,fmt,ap); } while (0)
-+# else
-+#  define _VCOS_LOG_X(cat, _level, fmt...) (void)0
-+#  define _VCOS_VLOG_X(cat, _level, fmt, ap) (void)0
-+# endif
-+
-+
-+
-+# define vcos_log_error(...)   _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_ERROR, __VA_ARGS__)
-+# define vcos_log_warn(...)    _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_WARN, __VA_ARGS__)
-+# define vcos_log_info(...)    _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_INFO, __VA_ARGS__)
-+# define vcos_log_trace(...)   _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_TRACE, __VA_ARGS__)
-+
-+# define vcos_vlog_error(fmt,ap)  _VCOS_VLOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_ERROR, fmt, ap)
-+# define vcos_vlog_warn(fmt,ap)   _VCOS_VLOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_WARN, fmt, ap)
-+# define vcos_vlog_info(fmt,ap)   _VCOS_VLOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_INFO, fmt, ap)
-+# define vcos_vlog_trace(fmt,ap)  _VCOS_VLOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_TRACE, fmt, ap)
-+
-+# define vcos_log(...)   _VCOS_LOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_INFO, __VA_ARGS__)
-+# define vcos_vlog(fmt,ap)  _VCOS_VLOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_INFO, fmt, ap)
-+# define VCOS_ALERT(...) _VCOS_LOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_ERROR, __VA_ARGS__)
-+# define VCOS_TRACE(...) _VCOS_LOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_INFO, __VA_ARGS__)
-+
-+/*
-+ * MS Visual Studio - pre 2005 does not grok variadic macros
-+ */
-+#elif defined(_MSC_VER)
-+
-+# if _MSC_VER >= 1400
-+
-+#  if !defined(NDEBUG) || defined(VCOS_ALWAYS_WANT_LOGGING)
-+#   define VCOS_LOGGING_ENABLED
-+#   define _VCOS_LOG_X(cat, _level, fmt,...) do { if (vcos_is_log_enabled(cat,_level)) vcos_log_impl(cat, _level, fmt, __VA_ARGS__); } while (0)
-+#  else
-+#   define _VCOS_LOG_X(cat, _level, fmt,...) (void)0
-+#  endif
-+
-+# define vcos_log_error(fmt,...)   _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_ERROR, fmt, __VA_ARGS__)
-+# define vcos_log_warn(fmt,...)    _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_WARN, fmt, __VA_ARGS__)
-+# define vcos_log_info(fmt,...)    _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_INFO, fmt, __VA_ARGS__)
-+# define vcos_log_trace(fmt,...)   _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_TRACE, fmt, __VA_ARGS__)
-+
-+# define vcos_log(fmt,...)   _VCOS_LOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_INFO, fmt)
-+# define VCOS_ALERT(fmt,...) _VCOS_LOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_ERROR, fmt)
-+# define VCOS_TRACE(fmt,...) _VCOS_LOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_INFO, fmt)
-+
-+# else /* _MSC_VER >= 1400 */
-+
-+/* do not define these */
-+
-+# endif /* _MSC_VER >= 1400 */
-+
-+#endif
-+
-+#if VCOS_HAVE_CMD
-+
-+#include "interface/vcos/vcos_cmd.h"
-+
-+/*
-+ * These are the log sub-commands. They're exported here for user-mode apps which 
-+ * may want to call these, since the "log" command isn't registered for user-mode 
-+ * apps (vcdbg for example, has its own log command). 
-+ */
-+VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_log_assert_cmd( VCOS_CMD_PARAM_T *param );
-+VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_log_set_cmd( VCOS_CMD_PARAM_T *param );
-+VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_log_status_cmd( VCOS_CMD_PARAM_T *param );
-+VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_log_test_cmd( VCOS_CMD_PARAM_T *param );
-+#endif
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif /* VCOS_LOGGING_H */
-+
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_lowlevel_thread.h
-@@ -0,0 +1,107 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - low level thread support
-+=============================================================================*/
-+
-+#ifndef VCOS_LOWLEVEL_THREAD_H
-+#define VCOS_LOWLEVEL_THREAD_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+#include "vcos_platform.h"
-+
-+/**
-+ * \file
-+ *
-+ * This defines a low level thread API that is supported by *some* operating systems
-+ * and can be used to construct the regular "joinable thread" API on those operating
-+ * systems.
-+ *
-+ * Most clients will not need to use this code.
-+ *
-+ * \sa vcos_joinable_thread.h
-+ */
-+
-+/**
-+  * \brief Create a thread.
-+  *
-+  * This creates a thread which can be stopped either by returning from the
-+  * entry point function or by calling vcos_llthread_exit from within the entry
-+  * point function. The thread must be cleaned up by calling
-+  * vcos_llthread_delete. vcos_llthread_delete may or may not terminate the
-+  * thread.
-+  *
-+  * The preemptible parameter familiar from Nucleus is removed, as it is unused in
-+  *  VideoCore code. Affinity is added, since we do use this.
-+  *
-+  * @param thread       Filled in with thread instance
-+  * @param name         An optional name for the thread. "" may be used (but
-+  *                     a name will aid in debugging).
-+  * @param entry        Entry point
-+  * @param arg          A single argument passed to the entry point function
-+  * @param stack        Pointer to stack address
-+  * @param stacksz      Size of stack in bytes
-+  * @param priority     Priority of task, between VCOS_PRI_LOW and VCOS_PRI_HIGH
-+  * @param affinity     CPU affinity
-+  *
-+  * @sa vcos_llthread_terminate vcos_llthread_delete
-+  */
-+VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_llthread_create(VCOS_LLTHREAD_T *thread,
-+                                                      const char *name,
-+                                                      VCOS_LLTHREAD_ENTRY_FN_T entry,
-+                                                      void *arg,
-+                                                      void *stack,
-+                                                      VCOS_UNSIGNED stacksz,
-+                                                      VCOS_UNSIGNED priority,
-+                                                      VCOS_UNSIGNED affinity,
-+                                                      VCOS_UNSIGNED timeslice,
-+                                                      VCOS_UNSIGNED autostart);
-+
-+/**
-+  * \brief Exits the current thread.
-+  */
-+VCOSPRE_ void VCOSPOST_ vcos_llthread_exit(void);
-+
-+/**
-+  * \brief Delete a thread. This must be called to cleanup after
-+  * vcos_llthread_create. This may or may not terminate the thread.
-+  * It does not clean up any resources that may have been
-+  * allocated by the thread.
-+  */
-+VCOSPRE_ void VCOSPOST_ vcos_llthread_delete(VCOS_LLTHREAD_T *thread);
-+
-+/**
-+  * \brief Return current lowlevel thread pointer.
-+  */
-+VCOS_INLINE_DECL
-+VCOS_LLTHREAD_T *vcos_llthread_current(void);
-+
-+/**
-+  * Resume a thread.
-+  */
-+VCOS_INLINE_DECL
-+void vcos_llthread_resume(VCOS_LLTHREAD_T *thread);
-+
-+VCOSPRE_ int VCOSPOST_ vcos_llthread_running(VCOS_LLTHREAD_T *thread);
-+
-+/**
-+  * \brief Create a VCOS_LLTHREAD_T for the current thread. This is so we can
-+  * have VCOS_LLTHREAD_Ts even for threads not originally created by VCOS (eg
-+  * the thread that calls vcos_init).
-+  */
-+extern VCOS_STATUS_T _vcos_llthread_create_attach(VCOS_LLTHREAD_T *thread);
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_mem.h
-@@ -0,0 +1,81 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - memory support
-+=============================================================================*/
-+
-+#ifndef VCOS_MEM_H
-+#define VCOS_MEM_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+#include "vcos_platform.h"
-+
-+/** \file
-+  *
-+  * Memory allocation api (malloc/free equivalents) is for benefit of host
-+  * applications. VideoCore code should use rtos_XXX functions.
-+  *
-+  */
-+
-+
-+/** Allocate memory
-+  *
-+  * @param size Size of memory to allocate
-+  * @param description Description, to aid in debugging. May be ignored internally on some platforms.
-+  */
-+VCOS_INLINE_DECL
-+void *vcos_malloc(VCOS_UNSIGNED size, const char *description);
-+
-+void *vcos_kmalloc(VCOS_UNSIGNED size, const char *description);
-+void *vcos_kcalloc(VCOS_UNSIGNED num, VCOS_UNSIGNED size, const char *description);
-+
-+/** Allocate cleared memory
-+  *
-+  * @param num Number of items to allocate.
-+  * @param size Size of each item in bytes.
-+  * @param description Description, to aid in debugging. May be ignored internally on some platforms.
-+  */
-+VCOS_INLINE_DECL
-+void *vcos_calloc(VCOS_UNSIGNED num, VCOS_UNSIGNED size, const char *description);
-+
-+/** Free memory
-+  *
-+  * Free memory that has been allocated.
-+  */
-+VCOS_INLINE_DECL
-+void vcos_free(void *ptr);
-+
-+void vcos_kfree(void *ptr);
-+
-+/** Allocate aligned memory
-+  *
-+  * Allocate memory aligned on the specified boundary.
-+  *
-+  * @param size Size of memory to allocate
-+  * @param description Description, to aid in debugging. May be ignored internally on some platforms.
-+  */
-+VCOS_INLINE_DECL
-+void *vcos_malloc_aligned(VCOS_UNSIGNED size, VCOS_UNSIGNED align, const char *description);
-+
-+/** Return the amount of free heap memory
-+  *
-+  */
-+VCOS_INLINE_DECL
-+unsigned long vcos_get_free_mem(void);
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif
-+
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_msgqueue.h
-@@ -0,0 +1,157 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VCOS - packet-like messages, based loosely on those found in TRIPOS.
-+=============================================================================*/
-+
-+#ifndef VCOS_MSGQUEUE_H
-+#define VCOS_MSGQUEUE_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+#include "vcos_platform.h"
-+
-+/**
-+ * \file
-+ *
-+ * Packet-like messages, based loosely on those found in TRIPOS and
-+ * derivatives thereof.
-+ *
-+ * A task can send a message *pointer* to another task, where it is
-+ * queued on a linked list and the task woken up. The receiving task
-+ * consumes all of the messages on its input queue, and optionally
-+ * sends back replies using the original message memory.
-+ *
-+ * A caller can wait for the reply to a specific message - any other
-+ * messages that arrive in the meantime are queued separately.
-+ *
-+ *
-+ * All messages have a standard common layout, but the payload area can
-+ * be used freely to extend this.
-+ */
-+
-+/** Map the payload portion of a message to a structure pointer.
-+  */
-+#define VCOS_MSG_DATA(_msg) (void*)((_msg)->data)
-+
-+/** Standard message ids - FIXME - these need to be done properly! */
-+#define VCOS_MSG_N_QUIT            1
-+#define VCOS_MSG_N_OPEN            2
-+#define VCOS_MSG_N_CLOSE           3
-+#define VCOS_MSG_N_PRIVATE         (1<<20)
-+
-+#define VCOS_MSG_REPLY_BIT         (1<<31)
-+
-+/** Make gnuc compiler be happy about pointer punning */
-+#ifdef __GNUC__
-+#define __VCOS_MAY_ALIAS __attribute__((__may_alias__))
-+#else
-+#define __VCOS_MAY_ALIAS
-+#endif
-+
-+/** A single message queue.
-+  */
-+typedef struct VCOS_MSGQUEUE_T
-+{
-+   struct VCOS_MSG_T *head;            /**< head of linked list of messages waiting on this queue */
-+   struct VCOS_MSG_T *tail;            /**< tail of message queue */
-+   VCOS_SEMAPHORE_T sem;               /**< thread waits on this for new messages */
-+   VCOS_MUTEX_T lock;                  /**< locks the messages list */
-+} VCOS_MSGQUEUE_T;
-+
-+/** A single message
-+  */
-+typedef struct VCOS_MSG_T
-+{
-+   uint32_t code;                      /**< message code */
-+   int error;                          /**< error status signalled back to caller */
-+   VCOS_MSGQUEUE_T *dst;               /**< destination queue */
-+   VCOS_MSGQUEUE_T *src;               /**< source; replies go back to here */
-+   struct VCOS_MSG_T *next;            /**< next in queue */
-+   VCOS_THREAD_T *src_thread;          /**< for debug */
-+   uint32_t data[25];                  /**< payload area */
-+} VCOS_MSG_T;
-+   
-+/** An endpoint
-+  */
-+typedef struct VCOS_MSG_ENDPOINT_T
-+{
-+   VCOS_MSGQUEUE_T primary;            /**< incoming messages */
-+   VCOS_MSGQUEUE_T secondary;          /**< this is used for waitspecific */
-+   char name[32];                      /**< name of this endpoint, for find() */
-+   struct VCOS_MSG_ENDPOINT_T *next;   /**< next in global list of endpoints */
-+} VCOS_MSG_ENDPOINT_T;
-+#define MSG_REPLY_BIT (1<<31)
-+
-+/** Initalise the library. Normally called from vcos_init().
-+  */
-+extern VCOS_STATUS_T vcos_msgq_init(void);
-+
-+/** Find a message queue by name and get a handle to it.
-+  *
-+  * @param name  the name of the queue to find
-+  *
-+  * @return The message queue, or NULL if not found.
-+  */
-+VCOSPRE_ VCOS_MSGQUEUE_T VCOSPOST_ *vcos_msgq_find(const char *name);
-+
-+/** Wait for a message queue to come into existence. If it already exists,
-+  * return immediately, otherwise block.
-+  *
-+  * On the whole, if you find yourself using this, it is probably a sign
-+  * of poor design, since you should create all the server threads first,
-+  * and then the client threads. But it is sometimes useful.
-+  *
-+  * @param name  the name of the queue to find
-+  * @return The message queue
-+  */
-+VCOSPRE_ VCOS_MSGQUEUE_T VCOSPOST_ *vcos_msgq_wait(const char *name);
-+
-+/** Send a message.
-+  */
-+VCOSPRE_ void VCOSPOST_ vcos_msg_send(VCOS_MSGQUEUE_T *dest, uint32_t code, VCOS_MSG_T *msg);
-+
-+/** Send a message and wait for a reply.
-+  */
-+VCOSPRE_ void VCOSPOST_ vcos_msg_sendwait(VCOS_MSGQUEUE_T *queue, uint32_t code, VCOS_MSG_T *msg);
-+
-+/** Wait for a message on this thread's endpoint.
-+  */
-+VCOSPRE_ VCOS_MSG_T * VCOSPOST_ vcos_msg_wait(void);
-+
-+/** Wait for a specific message.
-+  */
-+VCOS_MSG_T * vcos_msg_wait_specific(VCOS_MSGQUEUE_T *queue, VCOS_MSG_T *msg);
-+
-+/** Peek for a message on this thread's endpoint, if a message is not available, NULL is 
-+    returned. If a message is available it will be removed from the endpoint and returned.
-+  */
-+VCOSPRE_ VCOS_MSG_T * VCOSPOST_ vcos_msg_peek(void);
-+
-+/** Send a reply to a message
-+  */
-+VCOSPRE_ void VCOSPOST_ vcos_msg_reply(VCOS_MSG_T *msg);
-+
-+/** Create an endpoint. Each thread should need no more than one of these - if you 
-+  * find yourself needing a second one, you've done something wrong.
-+  */
-+VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_msgq_endpoint_create(VCOS_MSG_ENDPOINT_T *ep, const char *name);
-+
-+/** Destroy an endpoint.
-+  */
-+VCOSPRE_ void  VCOSPOST_ vcos_msgq_endpoint_delete(VCOS_MSG_ENDPOINT_T *ep);
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif
-+
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_mutex.h
-@@ -0,0 +1,92 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - mutex public header file
-+=============================================================================*/
-+
-+#ifndef VCOS_MUTEX_H
-+#define VCOS_MUTEX_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+#include "vcos_platform.h"
-+
-+/**
-+ * \file vcos_mutex.h
-+ *
-+ * Mutex API. Mutexes are not re-entrant, as supporting this adds extra code
-+ * that slows down clients which have been written sensibly.
-+ *
-+ * \sa vcos_reentrant_mutex.h
-+ *
-+ */
-+
-+/** Create a mutex.
-+  *
-+  * @param m      Filled in with mutex on return
-+  * @param name   A non-null name for the mutex, used for diagnostics.
-+  *
-+  * @return VCOS_SUCCESS if mutex was created, or error code.
-+  */
-+VCOS_INLINE_DECL
-+VCOS_STATUS_T vcos_mutex_create(VCOS_MUTEX_T *m, const char *name);
-+
-+/** Delete the mutex.
-+  */
-+VCOS_INLINE_DECL
-+void vcos_mutex_delete(VCOS_MUTEX_T *m);
-+
-+/**
-+  * \brief Wait to claim the mutex.
-+  *
-+  * On most platforms this always returns VCOS_SUCCESS, and so would ideally be
-+  * a void function, however some platforms allow a wait to be interrupted so
-+  * it remains non-void.
-+  *
-+  * Try to obtain the mutex.
-+  * @param m   Mutex to wait on
-+  * @return VCOS_SUCCESS - mutex was taken.
-+  *         VCOS_EAGAIN  - could not take mutex.
-+  */
-+#ifndef vcos_mutex_lock
-+VCOS_INLINE_DECL
-+VCOS_STATUS_T vcos_mutex_lock(VCOS_MUTEX_T *m);
-+
-+/** Release the mutex.
-+  */
-+VCOS_INLINE_DECL
-+void vcos_mutex_unlock(VCOS_MUTEX_T *m);
-+#endif
-+
-+/** Test if the mutex is already locked.
-+  *
-+  * @return 1 if mutex is locked, 0 if it is unlocked.
-+  */
-+VCOS_INLINE_DECL
-+int vcos_mutex_is_locked(VCOS_MUTEX_T *m);
-+
-+/** Obtain the mutex if possible.
-+  *
-+  * @param m  the mutex to try to obtain
-+  *
-+  * @return VCOS_SUCCESS if mutex is succesfully obtained, or VCOS_EAGAIN
-+  * if it is already in use by another thread.
-+  */
-+#ifndef vcos_mutex_trylock
-+VCOS_INLINE_DECL
-+VCOS_STATUS_T vcos_mutex_trylock(VCOS_MUTEX_T *m);
-+#endif
-+
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_once.h
-@@ -0,0 +1,42 @@
-+/*=============================================================================
-+Copyright (c) 2011 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - 'once'
-+=============================================================================*/
-+
-+#ifndef VCOS_ONCE_H
-+#define VCOS_ONCE_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+#include "vcos_platform.h"
-+
-+/**
-+ * \file vcos_once.h
-+ *
-+ * Ensure something is called only once.
-+ *
-+ * Initialize once_control to VCOS_ONCE_INIT. The first
-+ * time this is called, the init_routine will be called. Thereafter
-+ * it won't.
-+ *
-+ * \sa pthread_once()
-+ *
-+ */
-+
-+VCOS_STATUS_T vcos_once(VCOS_ONCE_T *once_control,
-+                        void (*init_routine)(void));
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_semaphore.h
-@@ -0,0 +1,115 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - public header file
-+=============================================================================*/
-+
-+#ifndef VCOS_SEMAPHORE_H
-+#define VCOS_SEMAPHORE_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+#include "vcos_platform.h"
-+
-+/**
-+ * \file vcos_semaphore.h
-+ *
-+ * \section sem Semaphores
-+ *
-+ * This provides counting semaphores. Semaphores are not re-entrant. On sensible
-+ * operating systems a semaphore can always be posted but can only be taken in 
-+ * thread (not interrupt) context. Under Nucleus, a LISR cannot post a semaphore,
-+ * although it would not be hard to lift this restriction.
-+ *
-+ * \subsection timeout Timeout
-+ *
-+ * On both Nucleus and ThreadX a semaphore can be taken with a timeout. This is
-+ * not supported by VCOS because it makes the non-timeout code considerably more
-+ * complicated (and hence slower). In the unlikely event that you need a timeout
-+ * with a semaphore, and you cannot simply redesign your code to avoid it, use
-+ * an event flag (vcos_event_flags.h).
-+ *
-+ * \subsection sem_nucleus Changes from Nucleus:
-+ *
-+ *  Semaphores are always "FIFO" - i.e. sleeping threads are woken in FIFO order. That's
-+ *  because:
-+ *  \arg there's no support for NU_PRIORITY in threadx (though it can be emulated, slowly)
-+ *  \arg we don't appear to actually consciously use it - for example, Dispmanx uses
-+ *  it, but all threads waiting are the same priority.
-+ *         
-+ */
-+
-+/** 
-+  * \brief Create a semaphore.
-+  *
-+  * Create a semaphore.
-+  *
-+  * @param sem   Pointer to memory to be initialized
-+  * @param name  A name for this semaphore. The name may be truncated internally.
-+  * @param count The initial count for the semaphore.
-+  *
-+  * @return VCOS_SUCCESS if the semaphore was created.
-+  * 
-+  */
-+VCOS_INLINE_DECL
-+VCOS_STATUS_T vcos_semaphore_create(VCOS_SEMAPHORE_T *sem, const char *name, VCOS_UNSIGNED count);
-+
-+/**
-+  * \brief Wait on a semaphore.
-+  *
-+  * There is no timeout option on a semaphore, as adding this will slow down
-+  * implementations on some platforms. If you need that kind of behaviour, use
-+  * an event group.
-+  *
-+  * On most platforms this always returns VCOS_SUCCESS, and so would ideally be
-+  * a void function, however some platforms allow a wait to be interrupted so
-+  * it remains non-void.
-+  *
-+  * @param sem Semaphore to wait on
-+  * @return VCOS_SUCCESS - semaphore was taken.
-+  *         VCOS_EAGAIN  - could not take semaphore
-+  *
-+  */
-+VCOS_INLINE_DECL
-+VCOS_STATUS_T vcos_semaphore_wait(VCOS_SEMAPHORE_T *sem);
-+
-+/**
-+  * \brief Try to wait for a semaphore.
-+  *
-+  * Try to obtain the semaphore. If it is already taken, return VCOS_TIMEOUT.
-+  * @param sem Semaphore to wait on
-+  * @return VCOS_SUCCESS - semaphore was taken.
-+  *         VCOS_EAGAIN - could not take semaphore
-+  */
-+VCOS_INLINE_DECL
-+VCOS_STATUS_T vcos_semaphore_trywait(VCOS_SEMAPHORE_T *sem);
-+
-+/**
-+  * \brief Post a semaphore.
-+  *
-+  * @param sem Semaphore to wait on
-+  */
-+VCOS_INLINE_DECL
-+VCOS_STATUS_T vcos_semaphore_post(VCOS_SEMAPHORE_T *sem);
-+
-+/**
-+  * \brief Delete a semaphore, releasing any resources consumed by it.
-+  *
-+  * @param sem Semaphore to wait on
-+  */
-+VCOS_INLINE_DECL
-+void vcos_semaphore_delete(VCOS_SEMAPHORE_T *sem);
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_stdbool.h
-@@ -0,0 +1,17 @@
-+#ifndef VCOS_STDBOOL_H
-+#define VCOS_STDBOOL_H
-+
-+#ifndef __cplusplus
-+
-+#if defined(__STDC__) && (__STDC_VERSION__ >= 199901L)
-+#include <stdbool.h>
-+#else
-+typedef enum {
-+   false,
-+   true
-+} bool;
-+#endif
-+
-+#endif /* __cplusplus */
-+
-+#endif
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_stdint.h
-@@ -0,0 +1,193 @@
-+/*=============================================================================
-+Copyright (c) 2011 Broadcom Europe Limited.
-+All rights reserved.
-+
-+FILE DESCRIPTION
-+
-+=============================================================================*/
-+
-+#ifndef VCOS_STDINT_H
-+#define VCOS_STDINT_H
-+
-+/* Attempt to provide the types defined in stdint.h.
-+ *
-+ * Ideally this would either call out to a platform-specific
-+ * header file (e.g. stdint.h) or define the types on a
-+ * per-architecture/compiler basis. But for now we just
-+ * use #ifdefs.
-+ */
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#ifdef __SYMBIAN32__
-+
-+typedef signed   char      int8_t;
-+typedef unsigned char      uint8_t;
-+
-+typedef signed   short     int16_t;
-+typedef unsigned short     uint16_t;
-+
-+typedef int16_t            int_least16_t;
-+
-+typedef signed   long      int32_t;
-+typedef unsigned long      uint32_t;
-+
-+typedef signed long long   int64_t;
-+typedef unsigned long long uint64_t;
-+
-+typedef int32_t            intptr_t;
-+typedef uint32_t           uintptr_t;
-+
-+typedef int64_t            intmax_t;
-+typedef uint64_t           uintmax_t;
-+
-+#define INT8_MIN SCHAR_MIN
-+#define INT8_MAX SCHAR_MAX
-+#define UINT8_MAX UCHAR_MAX
-+#define INT16_MIN SHRT_MIN
-+#define INT16_MAX SHRT_MAX
-+#define UINT16_MAX USHRT_MAX
-+#define INT32_MIN LONG_MIN
-+#define INT32_MAX LONG_MAX
-+#define UINT32_MAX ULONG_MAX
-+#define INT64_MIN LLONG_MIN
-+#define INT64_MAX LLONG_MAX
-+#define UINT64_MAX ULLONG_MAX
-+
-+#define INTPTR_MIN INT32_MIN
-+#define INTPTR_MAX INT32_MAX
-+#define UINTPTR_MAX UINT32_MAX
-+#define INTMAX_MIN INT64_MIN
-+#define INTMAX_MAX INT64_MAX
-+#define INT_LEAST16_MAX INT16_MAX
-+#define INT_LEAST16_MAX INT16_MAX
-+
-+/*{{{ C99 types  - THIS WHOLE SECTION IS INCOMPATIBLE WITH C99. IT SHOULD RESIDE IN A STDINT.H SINCE THIS FILE GETS USED ON HOST SIDE */
-+
-+#elif defined( __STDC__ ) && __STDC_VERSION__ >= 199901L
-+
-+#include <stdint.h>
-+
-+#elif defined( __GNUC__ )
-+
-+#include <stdint.h>
-+
-+#elif defined(_MSC_VER)                     /* Visual C define equivalent types */
-+
-+#include <stddef.h> /* Avoids intptr_t being defined in vadefs.h */
-+
-+typedef          __int8    int8_t;
-+typedef unsigned __int8    uint8_t;
-+
-+typedef          __int16   int16_t;
-+typedef unsigned __int16   uint16_t;
-+
-+typedef          __int32   int32_t;
-+typedef unsigned __int32   uint32_t;
-+
-+typedef          __int64   int64_t;
-+typedef unsigned __int64   uint64_t;
-+typedef uint32_t           uintptr_t;
-+typedef int64_t            intmax_t;
-+typedef uint64_t           uintmax_t;
-+typedef int16_t            int_least16_t;
-+
-+#elif defined (VCMODS_LCC)
-+#include <limits.h>
-+
-+typedef signed   char      int8_t;
-+typedef unsigned char      uint8_t;
-+
-+typedef signed   short     int16_t;
-+typedef unsigned short     uint16_t;
-+
-+typedef signed   long      int32_t;
-+typedef unsigned long      uint32_t;
-+
-+typedef signed   long      int64_t; /*!!!! PFCD, this means code using 64bit numbers will be broken on the VCE */
-+typedef unsigned long      uint64_t; /* !!!! PFCD */
-+
-+typedef int32_t            intptr_t;
-+typedef uint32_t           uintptr_t;
-+typedef int64_t            intmax_t;
-+typedef uint64_t           uintmax_t;
-+typedef int16_t            int_least16_t;
-+
-+#define INT8_MIN SCHAR_MIN
-+#define INT8_MAX SCHAR_MAX
-+#define UINT8_MAX UCHAR_MAX
-+#define INT16_MIN SHRT_MIN
-+#define INT16_MAX SHRT_MAX
-+#define UINT16_MAX USHRT_MAX
-+#define INT32_MIN LONG_MIN
-+#define INT32_MAX LONG_MAX
-+#define UINT32_MAX ULONG_MAX
-+#define INT64_MIN LONG_MIN /* !!!! PFCD */
-+#define INT64_MAX LONG_MAX /* !!!! PFCD */
-+#define UINT64_MAX ULONG_MAX /* !!!! PFCD */
-+
-+#define INTPTR_MIN INT32_MIN
-+#define INTPTR_MAX INT32_MAX
-+#define UINTPTR_MAX UINT32_MAX
-+#define INTMAX_MIN INT64_MIN
-+#define INTMAX_MIN INT64_MIN
-+#define INT_LEAST16_MAX INT16_MAX
-+#define INT_LEAST16_MAX INT16_MAX
-+
-+#elif defined(__VIDEOCORE__)
-+
-+typedef signed   char      int8_t;
-+typedef unsigned char      uint8_t;
-+
-+typedef signed   short     int16_t;
-+typedef unsigned short     uint16_t;
-+
-+typedef signed   long      int32_t;
-+typedef unsigned long      uint32_t;
-+
-+typedef signed   long long int64_t;
-+typedef unsigned long long uint64_t;
-+
-+typedef int32_t            intptr_t;
-+typedef uint32_t           uintptr_t;
-+typedef int64_t            intmax_t;
-+typedef uint64_t           uintmax_t;
-+typedef int16_t            int_least16_t;
-+
-+#define INT8_MIN SCHAR_MIN
-+#define INT8_MAX SCHAR_MAX
-+#define UINT8_MAX UCHAR_MAX
-+#define INT16_MIN SHRT_MIN
-+#define INT16_MAX SHRT_MAX
-+#define UINT16_MAX USHRT_MAX
-+#define INT32_MIN LONG_MIN
-+#define INT32_MAX LONG_MAX
-+#define UINT32_MAX ULONG_MAX
-+#define INT64_MIN LLONG_MIN
-+#define INT64_MAX LLONG_MAX
-+#define UINT64_MAX ULLONG_MAX
-+
-+#define INTPTR_MIN INT32_MIN
-+#define INTPTR_MAX INT32_MAX
-+#define UINTPTR_MAX UINT32_MAX
-+#define INTMAX_MIN INT64_MIN
-+#define INTMAX_MAX INT64_MAX
-+#define INT_LEAST16_MAX INT16_MAX
-+#define INT_LEAST16_MAX INT16_MAX
-+
-+#elif defined (__HIGHC__) && defined(_I386)
-+
-+#include <stdint.h>
-+
-+#else
-+#error Unknown platform
-+#endif
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif /* VCOS_STDINT_H */
-+
-+
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_string.h
-@@ -0,0 +1,73 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - public header file
-+=============================================================================*/
-+
-+#ifndef VCOS_STRING_H
-+#define VCOS_STRING_H
-+
-+/**
-+  * \file
-+  *
-+  * String functions.
-+  *
-+  */
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+#include "vcos_platform.h"
-+
-+#ifdef __KERNEL__
-+#include <linux/string.h>
-+#else
-+#include <string.h>
-+#endif
-+
-+/** Case insensitive string comparison.
-+  *
-+  */
-+
-+VCOS_INLINE_DECL
-+int vcos_strcasecmp(const char *s1, const char *s2);
-+
-+VCOS_INLINE_DECL
-+int vcos_strncasecmp(const char *s1, const char *s2, size_t n);
-+
-+VCOSPRE_ int VCOSPOST_ vcos_vsnprintf( char *buf, size_t buflen, const char *fmt, va_list ap );
-+
-+VCOSPRE_ int VCOSPOST_ vcos_snprintf(char *buf, size_t buflen, const char *fmt, ...);
-+
-+VCOS_STATIC_INLINE
-+int vcos_strlen(const char *s) { return (int)strlen(s); }
-+
-+VCOS_STATIC_INLINE
-+int vcos_strcmp(const char *s1, const char *s2) { return strcmp(s1,s2); }
-+
-+VCOS_STATIC_INLINE
-+int vcos_strncmp(const char *cs, const char *ct, size_t count) { return strncmp(cs, ct, count); }
-+
-+VCOS_STATIC_INLINE
-+char *vcos_strcpy(char *dst, const char *src) { return strcpy(dst, src); }
-+
-+VCOS_STATIC_INLINE
-+char *vcos_strncpy(char *dst, const char *src, size_t count) { return strncpy(dst, src, count); }
-+
-+VCOS_STATIC_INLINE
-+void *vcos_memcpy(void *dst, const void *src, size_t n) {  memcpy(dst, src, n);  return dst;  }
-+
-+VCOS_STATIC_INLINE
-+void *vcos_memset(void *p, int c, size_t n) { return memset(p, c, n); }
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_thread.h
-@@ -0,0 +1,259 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - public header file
-+=============================================================================*/
-+
-+#ifndef VCOS_THREAD_H
-+#define VCOS_THREAD_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+#include "vcos_platform.h"
-+
-+/**
-+ * \file vcos_thread.h
-+ *
-+ * \section thread Threads
-+ *
-+ * Under Nucleus, a thread is created by NU_Create_Task, passing in the stack
-+ * and various other parameters. To stop the thread, NU_Terminate_Thread() and
-+ * NU_Delete_Thread() are called.
-+ *
-+ * Unfortunately it's not possible to emulate this API under some fairly common
-+ * operating systems. Under Windows you can't pass in the stack, and you can't
-+ * safely terminate a thread.
-+ *
-+ * Therefore, an API which is similar to the pthreads API is used instead. This
-+ * API can (mostly) be emulated under all interesting operating systems.
-+ *
-+ * Obviously this makes the code somewhat more complicated on VideoCore than it
-+ * would otherwise be - we end up with an extra mutex per thread, and some code
-+ * that waits for it. The benefit is that we have a single way of creating
-+ * threads that works consistently on all platforms (apart from stack supplying).
-+ *
-+ * \subsection stack Stack
-+ *
-+ * It's still not possible to pass in the stack address, but this can be made
-+ * much more obvious in the API: the relevant function is missing and the
-+ * CPP symbol VCOS_CAN_SET_STACK_ADDR is zero rather than one.
-+ *
-+ * \subsection thr_create Creating a thread
-+ *
-+ * The simplest way to create a thread is with vcos_thread_create() passing in a
-+ * NULL thread parameter argument. To wait for the thread to exit, call
-+ * vcos_thread_join().
-+ *
-+ * \subsection back Backward compatibility
-+ *
-+ * To ease migration, a "classic" thread creation API is provided for code
-+ * that used to make use of Nucleus, vcos_thread_create_classic(). The
-+ * arguments are not exactly the same, as the PREEMPT parameter is dropped.
-+ *
-+ */
-+
-+#define VCOS_AFFINITY_CPU0    _VCOS_AFFINITY_CPU0
-+#define VCOS_AFFINITY_CPU1    _VCOS_AFFINITY_CPU1
-+#define VCOS_AFFINITY_MASK    _VCOS_AFFINITY_MASK
-+#define VCOS_AFFINITY_DEFAULT _VCOS_AFFINITY_DEFAULT
-+#define VCOS_AFFINITY_THISCPU _VCOS_AFFINITY_THISCPU
-+
-+/** Report whether or not we have an RTOS at all, and hence the ability to
-+  * create threads.
-+  */
-+VCOSPRE_ int VCOSPOST_ vcos_have_rtos(void);
-+
-+/** Create a thread. It must be cleaned up by calling vcos_thread_join().
-+  *
-+  * @param thread   Filled in on return with thread
-+  * @param name     A name for the thread. May be the empty string.
-+  * @param attrs    Attributes; default attributes will be used if this is NULL.
-+  * @param entry    Entry point.
-+  * @param arg      Argument passed to the entry point.
-+  */
-+VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_thread_create(VCOS_THREAD_T *thread,
-+                                                    const char *name,
-+                                                    VCOS_THREAD_ATTR_T *attrs,
-+                                                    VCOS_THREAD_ENTRY_FN_T entry,
-+                                                    void *arg);
-+
-+/** Exit the thread from within the thread function itself.
-+  * Resources must still be cleaned up via a call to thread_join().
-+  *
-+  * The thread can also be terminated by simply exiting the thread function.
-+  *
-+  * @param data Data passed to thread_join. May be NULL.
-+  */
-+VCOSPRE_ void VCOSPOST_ vcos_thread_exit(void *data);
-+
-+/** Wait for a thread to terminate and then clean up its resources.
-+  *
-+  * @param thread Thread to wait for
-+  * @param pData  Updated to point at data provided in vcos_thread_exit or exit
-+  * code of thread function.
-+  */
-+VCOSPRE_ void VCOSPOST_ vcos_thread_join(VCOS_THREAD_T *thread,
-+                             void **pData);
-+
-+
-+/**
-+  * \brief Create a thread using an API similar to the one "traditionally"
-+  * used under Nucleus.
-+  *
-+  * This creates a thread which must be cleaned up by calling vcos_thread_join().
-+  * The thread cannot be simply terminated (as in Nucleus and ThreadX) as thread
-+  * termination is not universally supported.
-+  *
-+  * @param thread       Filled in with thread instance
-+  * @param name         An optional name for the thread. NULL or "" may be used (but
-+  *                     a name will aid in debugging).
-+  * @param entry        Entry point
-+  * @param arg          A single argument passed to the entry point function
-+  * @param stack        Pointer to stack address
-+  * @param stacksz      Size of stack in bytes
-+  * @param priaff       Priority of task, between VCOS_PRI_LOW and VCOS_PRI_HIGH, ORed with the CPU affinity
-+  * @param autostart    If non-zero the thread will start immediately.
-+  * @param timeslice    Timeslice (system ticks) for this thread.
-+  *
-+  * @sa vcos_thread_terminate vcos_thread_delete
-+  */
-+VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_thread_create_classic(VCOS_THREAD_T *thread,
-+                                                            const char *name,
-+                                                            void *(*entry)(void *arg),
-+                                                            void *arg,
-+                                                            void *stack,
-+                                                            VCOS_UNSIGNED stacksz,
-+                                                            VCOS_UNSIGNED priaff,
-+                                                            VCOS_UNSIGNED timeslice,
-+                                                            VCOS_UNSIGNED autostart);
-+
-+/**
-+  * \brief Set a thread's priority
-+  *
-+  * Set the priority for a thread.
-+  *
-+  * @param thread  The thread
-+  * @param pri     Thread priority in VCOS_PRI_MASK bits; affinity in VCOS_AFFINITY_MASK bits.
-+  */
-+VCOS_INLINE_DECL
-+void vcos_thread_set_priority(VCOS_THREAD_T *thread, VCOS_UNSIGNED pri);
-+
-+/**
-+  * \brief Return the currently executing thread.
-+  *
-+  */
-+VCOS_INLINE_DECL
-+VCOS_THREAD_T *vcos_thread_current(void);
-+
-+/**
-+  * \brief Return the thread's priority.
-+  */
-+VCOS_INLINE_DECL
-+VCOS_UNSIGNED vcos_thread_get_priority(VCOS_THREAD_T *thread);
-+
-+/**
-+  * \brief Return the thread's cpu affinity.
-+  */
-+VCOS_INLINE_DECL
-+VCOS_UNSIGNED vcos_thread_get_affinity(VCOS_THREAD_T *thread);
-+
-+/**
-+  * \brief Set the thread's cpu affinity.
-+  */
-+
-+VCOS_INLINE_DECL
-+void vcos_thread_set_affinity(VCOS_THREAD_T *thread, VCOS_UNSIGNED affinity);
-+
-+/**
-+  * \brief Query whether we are in an interrupt.
-+  *
-+  * @return 1 if in interrupt context.
-+  */
-+VCOS_INLINE_DECL
-+int vcos_in_interrupt(void);
-+
-+/**
-+  * \brief Sleep a while.
-+  *
-+  * @param ms Number of milliseconds to sleep for
-+  *
-+  * This may actually sleep a whole number of ticks.
-+  */
-+VCOS_INLINE_DECL
-+void vcos_sleep(uint32_t ms);
-+
-+/**
-+  * \brief Return the value of the hardware microsecond counter.
-+  *
-+  */
-+VCOS_INLINE_DECL
-+uint32_t vcos_getmicrosecs(void);
-+
-+#define vcos_get_ms() (vcos_getmicrosecs()/1000)
-+
-+/**
-+  * \brief Return a unique identifier for the current process
-+  *
-+  */
-+VCOS_INLINE_DECL
-+VCOS_UNSIGNED vcos_process_id_current(void);
-+
-+/** Relinquish this time slice. */
-+VCOS_INLINE_DECL
-+void vcos_thread_relinquish(void);
-+
-+/** Return the name of the given thread.
-+  */
-+VCOSPRE_ const char * VCOSPOST_ vcos_thread_get_name(const VCOS_THREAD_T *thread);
-+
-+/** Change preemption. This is almost certainly not what you want, as it won't
-+  * work reliably in a multicore system: although you can affect the preemption
-+  * on *this* core, you won't affect what's happening on the other core(s).
-+  *
-+  * It's mainly here to ease migration. If you're using it in new code, you
-+  * probably need to think again.
-+  *
-+  * @param pe New preemption, VCOS_PREEMPT or VCOS_NO_PREEMPT
-+  * @return Old value of preemption.
-+  */
-+VCOS_INLINE_DECL
-+VCOS_UNSIGNED vcos_change_preemption(VCOS_UNSIGNED pe);
-+
-+/** Is a thread still running, or has it exited?
-+  *
-+  * Note: this exists for some fairly scary code in the video codec tests. Don't
-+  * try to use it for anything else, as it may well not do what you expect.
-+  *
-+  * @param thread   thread to query
-+  * @return non-zero if thread is running, or zero if it has exited.
-+  */
-+VCOS_INLINE_DECL
-+int vcos_thread_running(VCOS_THREAD_T *thread);
-+
-+/** Resume a thread.
-+  *
-+  * @param thread thread to resume
-+  */
-+VCOS_INLINE_DECL
-+void vcos_thread_resume(VCOS_THREAD_T *thread);
-+
-+/*
-+ * Internal APIs - may not always be present and should not be used in
-+ * client code.
-+ */
-+
-+extern void _vcos_task_timer_set(void (*pfn)(void*), void *, VCOS_UNSIGNED ms);
-+extern void _vcos_task_timer_cancel(void);
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_thread_attr.h
-@@ -0,0 +1,73 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - thread attributes
-+=============================================================================*/
-+
-+#ifndef VCOS_THREAD_ATTR_H
-+#define VCOS_THREAD_ATTR_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+/**
-+ * \file
-+ *
-+ * Attributes for thread creation.
-+ *
-+ */
-+
-+/** Initialize thread attribute struct. This call does not allocate memory,
-+  * and so cannot fail.
-+  *
-+  */
-+VCOSPRE_ void VCOSPOST_ vcos_thread_attr_init(VCOS_THREAD_ATTR_T *attrs);
-+
-+/** Set the stack address and size. If not set, a stack will be allocated automatically.
-+  *
-+  * This can only be set on some platforms. It will always be possible to set the stack
-+  * address on VideoCore, but on host platforms, support may well not be available.
-+  */
-+#if VCOS_CAN_SET_STACK_ADDR
-+VCOS_INLINE_DECL
-+void vcos_thread_attr_setstack(VCOS_THREAD_ATTR_T *attrs, void *addr, VCOS_UNSIGNED sz);
-+#endif
-+
-+/** Set the stack size. If not set, a default size will be used. Attempting to call this after having
-+  * set the stack location with vcos_thread_attr_setstack() will result in undefined behaviour.
-+  */
-+VCOS_INLINE_DECL
-+void vcos_thread_attr_setstacksize(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED sz);
-+
-+/** Set the task priority. If not set, a default value will be used.
-+  */
-+VCOS_INLINE_DECL
-+void vcos_thread_attr_setpriority(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED pri);
-+
-+/** Set the task cpu affinity. If not set, the default will be used.
-+  */
-+VCOS_INLINE_DECL
-+void vcos_thread_attr_setaffinity(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED aff);
-+
-+/** Set the timeslice. If not set the default will be used.
-+  */
-+VCOS_INLINE_DECL
-+void vcos_thread_attr_settimeslice(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED ts);
-+
-+/** The thread entry function takes (argc,argv), as per Nucleus, with
-+  * argc being 0. This may be withdrawn in a future release and should not
-+  * be used in new code.
-+  */
-+VCOS_INLINE_DECL
-+void _vcos_thread_attr_setlegacyapi(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED legacy);
-+
-+VCOS_INLINE_DECL
-+void vcos_thread_attr_setautostart(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED autostart);
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_timer.h
-@@ -0,0 +1,95 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+Project  :  vcfw
-+Module   :  chip driver
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - timer support
-+=============================================================================*/
-+
-+#ifndef VCOS_TIMER_H
-+#define VCOS_TIMER_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include "interface/vcos/vcos_types.h"
-+#include "vcos_platform.h"
-+
-+/** \file vcos_timer.h
-+  *
-+  * Timers are single shot.
-+  *
-+  * Timer times are in milliseconds.
-+  *
-+  * \note that timer callback functions are called from an arbitrary thread
-+  * context. The expiration function should do its work as quickly as possible;
-+  * blocking should be avoided.
-+  *
-+  * \note On Windows, the separate function vcos_timer_init() must be called
-+  * as timer initialization from DllMain is not possible.
-+  */
-+
-+/** Perform timer subsystem initialization. This function is not needed
-+  * on non-Windows platforms but is still present so that it can be
-+  * called. On Windows it is needed because vcos_init() gets called
-+  * from DLL initialization where it is not possible to create a
-+  * time queue (deadlock occurs if you try).
-+  *
-+  * @return VCOS_SUCCESS on success. VCOS_EEXIST if this has already been called
-+  * once. VCOS_ENOMEM if resource allocation failed.
-+  */
-+VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_timer_init(void);
-+
-+/** Create a timer in a disabled state.
-+  *
-+  * The timer is initially disabled.
-+  *
-+  * @param timer     timer handle
-+  * @param name      name for timer
-+  * @param expiration_routine function to call when timer expires
-+  * @param context   context passed to expiration routine
-+  *
-+  */
-+VCOS_INLINE_DECL
-+VCOS_STATUS_T vcos_timer_create(VCOS_TIMER_T *timer,
-+                                const char *name,
-+                                void (*expiration_routine)(void *context),
-+                                void *context);
-+
-+
-+
-+/** Start a timer running.
-+  *
-+  * Timer must be stopped.
-+  *
-+  * @param timer     timer handle
-+  * @param delay     Delay to wait for, in ms
-+  */
-+VCOS_INLINE_DECL
-+void vcos_timer_set(VCOS_TIMER_T *timer, VCOS_UNSIGNED delay);
-+
-+/** Stop an already running timer.
-+  *
-+  * @param timer     timer handle
-+  */
-+VCOS_INLINE_DECL
-+void vcos_timer_cancel(VCOS_TIMER_T *timer);
-+
-+/** Stop a timer and restart it.
-+  * @param timer     timer handle
-+  * @param delay     delay in ms
-+  */
-+VCOS_INLINE_DECL
-+void vcos_timer_reset(VCOS_TIMER_T *timer, VCOS_UNSIGNED delay);
-+
-+VCOS_INLINE_DECL
-+void vcos_timer_delete(VCOS_TIMER_T *timer);
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+#endif
---- /dev/null
-+++ b/drivers/misc/vc04_services/interface/vcos/vcos_types.h
-@@ -0,0 +1,197 @@
-+/*=============================================================================
-+Copyright (c) 2009 Broadcom Europe Limited.
-+All rights reserved.
-+
-+FILE DESCRIPTION
-+VideoCore OS Abstraction Layer - basic types
-+=============================================================================*/
-+
-+#ifndef VCOS_TYPES_H
-+#define VCOS_TYPES_H
-+
-+#define VCOS_VERSION   1
-+
-+#include "vcos_platform_types.h"
-+
-+#if !defined(VCOSPRE_) || !defined(VCOSPOST_)
-+#error VCOSPRE_ and VCOSPOST_ not defined!
-+#endif
-+
-+/* Redefine these here; this means that existing header files can carry on
-+ * using the VCHPOST/VCHPRE macros rather than having huge changes, which
-+ * could cause nasty merge problems.
-+ */
-+#ifndef VCHPOST_
-+#define VCHPOST_ VCOSPOST_
-+#endif
-+#ifndef VCHPRE_
-+#define VCHPRE_  VCOSPRE_
-+#endif
-+
-+/** Entry function for a lowlevel thread.
-+  *
-+  * Returns void for consistency with Nucleus/ThreadX.
-+  */
-+typedef void (*VCOS_LLTHREAD_ENTRY_FN_T)(void *);
-+
-+/** Thread entry point. Returns a void* for consistency
-+  * with pthreads.
-+  */
-+typedef void *(*VCOS_THREAD_ENTRY_FN_T)(void*);
-+
-+
-+/* Error return codes - chosen to be similar to errno values */
-+typedef enum
-+{
-+   VCOS_SUCCESS,
-+   VCOS_EAGAIN,
-+   VCOS_ENOENT,
-+   VCOS_ENOSPC,
-+   VCOS_EINVAL,
-+   VCOS_EACCESS,
-+   VCOS_ENOMEM,
-+   VCOS_ENOSYS,
-+   VCOS_EEXIST,
-+   VCOS_ENXIO,
-+   VCOS_EINTR
-+} VCOS_STATUS_T;
-+
-+/* Some compilers (MetaWare) won't inline with -g turned on, which then results
-+ * in a lot of code bloat. To overcome this, inline functions are forward declared
-+ * with the prefix VCOS_INLINE_DECL, and implemented with the prefix VCOS_INLINE_IMPL.
-+ *
-+ * That then means that in a release build, "static inline" can be used in the obvious
-+ * way, but in a debug build the implementations can be skipped in all but one file,
-+ * by using VCOS_INLINE_BODIES.
-+ *
-+ * VCOS_INLINE_DECL - put this at the start of an inline forward declaration of a VCOS
-+ * function.
-+ *
-+ * VCOS_INLINE_IMPL - put this at the start of an inlined implementation of a VCOS
-+ * function.
-+ *
-+ */
-+
-+/* VCOS_EXPORT - it turns out that in some circumstances we need the implementation of
-+ * a function even if it is usually inlined.
-+ *
-+ * In particular, if we have a codec that is usually provided in object form, if it
-+ * was built for a debug build it will be full of calls to vcos_XXX(). If this is used
-+ * in a *release* build, then there won't be any of these calls around in the main image
-+ * as they will all have been inlined. The problem also exists for vcos functions called
-+ * from assembler.
-+ *
-+ * VCOS_EXPORT ensures that the named function will be emitted as a regular (not static-inline)
-+ * function inside vcos_<platform>.c so that it can be linked against. Doing this for every
-+ * VCOS function would be a bit code-bloat-tastic, so it is only done for those that need it.
-+ *
-+ */
-+
-+#ifdef __cplusplus
-+#define _VCOS_INLINE inline
-+#else
-+#define _VCOS_INLINE __inline
-+#endif
-+
-+#if defined(NDEBUG)
-+
-+#ifdef __GNUC__
-+# define VCOS_INLINE_DECL extern __inline__
-+# define VCOS_INLINE_IMPL static __inline__
-+#else
-+# define VCOS_INLINE_DECL static _VCOS_INLINE   /* declare a func */
-+# define VCOS_INLINE_IMPL static _VCOS_INLINE   /* implement a func inline */
-+#endif
-+
-+# if defined(VCOS_WANT_IMPL)
-+#  define VCOS_EXPORT
-+# else
-+#  define VCOS_EXPORT VCOS_INLINE_IMPL
-+# endif /* VCOS_WANT_IMPL */
-+
-+#define VCOS_INLINE_BODIES
-+
-+#else /* NDEBUG */
-+
-+#if !defined(VCOS_INLINE_DECL)
-+   #define VCOS_INLINE_DECL extern
-+#endif
-+#if !defined(VCOS_INLINE_IMPL)
-+   #define VCOS_INLINE_IMPL
-+#endif
-+#define VCOS_EXPORT VCOS_INLINE_IMPL
-+#endif
-+
-+#define VCOS_STATIC_INLINE static _VCOS_INLINE
-+
-+#if defined(__HIGHC__) || defined(__HIGHC_ANSI__)
-+#define _VCOS_METAWARE
-+#endif
-+
-+/** It seems that __FUNCTION__ isn't standard!
-+  */
-+#if __STDC_VERSION__ < 199901L
-+# if __GNUC__ >= 2 || defined(__VIDEOCORE__)
-+#  define VCOS_FUNCTION __FUNCTION__
-+# else
-+#  define VCOS_FUNCTION "<unknown>"
-+# endif
-+#else
-+# define VCOS_FUNCTION __func__
-+#endif
-+
-+#define _VCOS_MS_PER_TICK (1000/VCOS_TICKS_PER_SECOND)
-+
-+/* Convert a number of milliseconds to a tick count. Internal use only - fails to
-+ * convert VCOS_SUSPEND correctly.
-+ */
-+#define _VCOS_MS_TO_TICKS(ms) (((ms)+_VCOS_MS_PER_TICK-1)/_VCOS_MS_PER_TICK)
-+
-+#define VCOS_TICKS_TO_MS(ticks) ((ticks) * _VCOS_MS_PER_TICK)
-+
-+/** VCOS version of DATESTR, from pcdisk.h. Used by the hostreq service.
-+ */ 
-+typedef struct vcos_datestr
-+{
-+   uint8_t       cmsec;              /**< Centesimal mili second */
-+   uint16_t      date;               /**< Date */
-+   uint16_t      time;               /**< Time */
-+
-+} VCOS_DATESTR;
-+
-+/* Compile-time assert - declares invalid array length if condition
-+ * not met, or array of length one if OK.
-+ */
-+#define VCOS_CASSERT(e) extern char vcos_compile_time_check[1/(e)]
-+
-+#define vcos_min(x,y) ((x) < (y) ? (x) : (y))
-+#define vcos_max(x,y) ((x) > (y) ? (x) : (y))
-+
-+/** Return the count of an array. FIXME: under gcc we could make
-+ * this report an error for pointers using __builtin_types_compatible().
-+ */
-+#define vcos_countof(x) (sizeof((x)) / sizeof((x)[0]))
-+
-+/* for backward compatibility */
-+#define countof(x) (sizeof((x)) / sizeof((x)[0]))
-+
-+#define VCOS_ALIGN_DOWN(p,n) (((ptrdiff_t)(p)) & ~((n)-1))
-+#define VCOS_ALIGN_UP(p,n) VCOS_ALIGN_DOWN((ptrdiff_t)(p)+(n)-1,(n))
-+
-+/** bool_t is not a POSIX type so cannot rely on it. Define it here.
-+  * It's not even defined in stdbool.h.
-+  */
-+typedef int32_t vcos_bool_t;
-+typedef int32_t vcos_fourcc_t;
-+
-+#define VCOS_FALSE   0
-+#define VCOS_TRUE    (!VCOS_FALSE)
-+
-+/** Mark unused arguments to keep compilers quiet */
-+#define vcos_unused(x) (void)(x)
-+
-+/** For backward compatibility */
-+typedef vcos_fourcc_t fourcc_t;
-+typedef vcos_fourcc_t FOURCC_T;
-+
-+#endif