aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-3.3/0005-bcm2708-vchiq-driver.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm2708/patches-3.3/0005-bcm2708-vchiq-driver.patch')
-rw-r--r--target/linux/brcm2708/patches-3.3/0005-bcm2708-vchiq-driver.patch16383
1 files changed, 0 insertions, 16383 deletions
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
index 47c6d8e875..0000000000
--- a/target/linux/brcm2708/patches-3.3/0005-bcm2708-vchiq-driver.patch
+++ /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