Author: gonzo
Date: Thu Feb  5 19:54:03 2015
New Revision: 278277
URL: https://svnweb.freebsd.org/changeset/base/278277

Log:
  Import VCHI driver for Broadcom's VideoCore IV GPU
  
  Differential Revision:        D1753

Added:
  head/sys/contrib/vchiq/
  head/sys/contrib/vchiq/interface/
  head/sys/contrib/vchiq/interface/compat/
  head/sys/contrib/vchiq/interface/compat/list.h   (contents, props changed)
  head/sys/contrib/vchiq/interface/compat/vchi_bsd.c   (contents, props changed)
  head/sys/contrib/vchiq/interface/compat/vchi_bsd.h   (contents, props changed)
  head/sys/contrib/vchiq/interface/vchi/
  head/sys/contrib/vchiq/interface/vchi/connections/
  head/sys/contrib/vchiq/interface/vchi/connections/connection.h   (contents, 
props changed)
  head/sys/contrib/vchiq/interface/vchi/message_drivers/
  head/sys/contrib/vchiq/interface/vchi/message_drivers/message.h   (contents, 
props changed)
  head/sys/contrib/vchiq/interface/vchi/vchi.h   (contents, props changed)
  head/sys/contrib/vchiq/interface/vchi/vchi_cfg.h   (contents, props changed)
  head/sys/contrib/vchiq/interface/vchi/vchi_cfg_internal.h   (contents, props 
changed)
  head/sys/contrib/vchiq/interface/vchi/vchi_common.h   (contents, props 
changed)
  head/sys/contrib/vchiq/interface/vchi/vchi_mh.h   (contents, props changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq.h   (contents, props changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835.h   (contents, props 
changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c   (contents, 
props changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_arm.c   (contents, props 
changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_arm.h   (contents, props 
changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_build_info.h   (contents, 
props changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_cfg.h   (contents, props 
changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_connected.c   (contents, 
props changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_connected.h   (contents, 
props changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_core.c   (contents, props 
changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_core.h   (contents, props 
changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_if.h   (contents, props 
changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_ioctl.h   (contents, props 
changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kern_lib.c   (contents, 
props changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c   (contents, props 
changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_memdrv.h   (contents, props 
changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_pagelist.h   (contents, 
props changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_proc.c   (contents, props 
changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_shim.c   (contents, props 
changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_util.c   (contents, props 
changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_util.h   (contents, props 
changed)
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_version.c   (contents, props 
changed)
Modified:
  head/sys/arm/broadcom/bcm2835/files.bcm2835
  head/sys/conf/kern.pre.mk

Modified: head/sys/arm/broadcom/bcm2835/files.bcm2835
==============================================================================
--- head/sys/arm/broadcom/bcm2835/files.bcm2835 Thu Feb  5 19:36:29 2015        
(r278276)
+++ head/sys/arm/broadcom/bcm2835/files.bcm2835 Thu Feb  5 19:54:03 2015        
(r278277)
@@ -27,3 +27,23 @@ kern/kern_clocksource.c                 
 
 dev/mbox/mbox_if.m                             standard
 dev/ofw/ofw_cpu.c                              standard
+
+# VideoCore driver
+contrib/vchiq/interface/compat/vchi_bsd.c      standard \
+       compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 
-I$S/contrib/vchiq"
+contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c     standard \
+       compile-with "${NORMAL_C} -Wno-unused -DUSE_VCHIQ_ARM 
-D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
+contrib/vchiq/interface/vchiq_arm/vchiq_arm.c  standard \
+       compile-with "${NORMAL_C} -Wno-unused -DUSE_VCHIQ_ARM 
-D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
+contrib/vchiq/interface/vchiq_arm/vchiq_connected.c    standard \
+       compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 
-I$S/contrib/vchiq"
+contrib/vchiq/interface/vchiq_arm/vchiq_core.c standard \
+       compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 
-I$S/contrib/vchiq"
+contrib/vchiq/interface/vchiq_arm/vchiq_kern_lib.c     standard \
+       compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 
-I$S/contrib/vchiq"
+contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c standard \
+       compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 
-I$S/contrib/vchiq"
+contrib/vchiq/interface/vchiq_arm/vchiq_shim.c standard \
+       compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 
-I$S/contrib/vchiq"
+contrib/vchiq/interface/vchiq_arm/vchiq_util.c standard \
+       compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 
-I$S/contrib/vchiq"

Modified: head/sys/conf/kern.pre.mk
==============================================================================
--- head/sys/conf/kern.pre.mk   Thu Feb  5 19:36:29 2015        (r278276)
+++ head/sys/conf/kern.pre.mk   Thu Feb  5 19:54:03 2015        (r278277)
@@ -79,6 +79,9 @@ INCLUDES+= -I$S/dev/ath -I$S/dev/ath/ath
 # ... and the same for the NgATM stuff
 INCLUDES+= -I$S/contrib/ngatm
 
+# ... and the same for vchiq
+INCLUDES+= -I$S/contrib/vchiq
+
 # ... and the same for twa
 INCLUDES+= -I$S/dev/twa
 

Added: head/sys/contrib/vchiq/interface/compat/list.h
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/contrib/vchiq/interface/compat/list.h      Thu Feb  5 19:54:03 
2015        (r278277)
@@ -0,0 +1,256 @@
+/*     $NetBSD: list.h,v 1.5 2014/08/20 15:26:52 riastradh Exp $       */
+
+/*-
+ * Copyright (c) 2013 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Taylor R. Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Notes on porting:
+ *
+ * - LIST_HEAD(x) means a declaration `struct list_head x =
+ *   LIST_HEAD_INIT(x)' in Linux, but something else in NetBSD.
+ *   Replace by the expansion.
+ *
+ * - The `_rcu' routines here are not actually pserialize(9)-safe.
+ *   They need dependent read memory barriers added.  Please fix this
+ *   if you need to use them with pserialize(9).
+ */
+
+#ifndef _LINUX_LIST_H_
+#define _LINUX_LIST_H_
+
+#include <sys/queue.h>
+
+#define container_of(ptr, type, member)                                \
+({                                                             \
+       __typeof(((type *)0)->member) *_p = (ptr);              \
+       (type *)((char *)_p - offsetof(type, member));          \
+})
+
+/*
+ * Doubly-linked lists.
+ */
+
+struct list_head {
+       struct list_head *prev;
+       struct list_head *next;
+};
+
+#define        LIST_HEAD_INIT(name)    { .prev = &(name), .next = &(name) }
+
+static inline void
+INIT_LIST_HEAD(struct list_head *head)
+{
+       head->prev = head;
+       head->next = head;
+}
+
+static inline struct list_head *
+list_first(const struct list_head *head)
+{
+       return head->next;
+}
+
+static inline struct list_head *
+list_last(const struct list_head *head)
+{
+       return head->prev;
+}
+
+static inline struct list_head *
+list_next(const struct list_head *node)
+{
+       return node->next;
+}
+
+static inline struct list_head *
+list_prev(const struct list_head *node)
+{
+       return node->prev;
+}
+
+static inline int
+list_empty(const struct list_head *head)
+{
+       return (head->next == head);
+}
+
+static inline int
+list_is_singular(const struct list_head *head)
+{
+
+       if (list_empty(head))
+               return false;
+       if (head->next != head->prev)
+               return false;
+       return true;
+}
+
+static inline void
+__list_add_between(struct list_head *prev, struct list_head *node,
+    struct list_head *next)
+{
+       prev->next = node;
+       node->prev = prev;
+       node->next = next;
+       next->prev = node;
+}
+
+static inline void
+list_add(struct list_head *node, struct list_head *head)
+{
+       __list_add_between(head, node, head->next);
+}
+
+static inline void
+list_add_tail(struct list_head *node, struct list_head *head)
+{
+       __list_add_between(head->prev, node, head);
+}
+
+static inline void
+list_del(struct list_head *entry)
+{
+       entry->prev->next = entry->next;
+       entry->next->prev = entry->prev;
+}
+
+static inline void
+__list_splice_between(struct list_head *prev, const struct list_head *list,
+    struct list_head *next)
+{
+       struct list_head *first = list->next;
+       struct list_head *last = list->prev;
+
+       first->prev = prev;
+       prev->next = first;
+
+       last->next = next;
+       next->prev = last;
+}
+
+static inline void
+list_splice(const struct list_head *list, struct list_head *head)
+{
+       if (!list_empty(list))
+               __list_splice_between(head, list, head->next);
+}
+
+static inline void
+list_splice_tail(const struct list_head *list, struct list_head *head)
+{
+       if (!list_empty(list))
+               __list_splice_between(head->prev, list, head);
+}
+
+static inline void
+list_move(struct list_head *node, struct list_head *head)
+{
+       list_del(node);
+       list_add(node, head);
+}
+
+static inline void
+list_move_tail(struct list_head *node, struct list_head *head)
+{
+       list_del(node);
+       list_add_tail(node, head);
+}
+
+static inline void
+list_replace(struct list_head *old, struct list_head *new)
+{
+       new->prev = old->prev;
+       old->prev->next = new;
+       new->next = old->next;
+       old->next->prev = new;
+}
+
+static inline void
+list_del_init(struct list_head *node)
+{
+       list_del(node);
+       INIT_LIST_HEAD(node);
+}
+
+#define        list_entry(PTR, TYPE, FIELD)    container_of(PTR, TYPE, FIELD)
+#define        list_first_entry(PTR, TYPE, FIELD)                              
\
+       list_entry(list_first((PTR)), TYPE, FIELD)
+#define        list_last_entry(PTR, TYPE, FIELD)                               
\
+       list_entry(list_last((PTR)), TYPE, FIELD)
+#define        list_next_entry(ENTRY, FIELD)                                   
\
+       list_entry(list_next(&(ENTRY)->FIELD), typeof(*(ENTRY)), FIELD)
+#define        list_prev_entry(ENTRY, FIELD)                                   
\
+       list_entry(list_prev(&(ENTRY)->FIELD), typeof(*(ENTRY)), FIELD)
+
+#define        list_for_each(VAR, HEAD)                                        
\
+       for ((VAR) = list_first((HEAD));                                \
+               (VAR) != (HEAD);                                        \
+               (VAR) = list_next((VAR)))
+
+#define        list_for_each_safe(VAR, NEXT, HEAD)                             
\
+       for ((VAR) = list_first((HEAD));                                \
+               ((VAR) != (HEAD)) && ((NEXT) = list_next((VAR)), 1);    \
+               (VAR) = (NEXT))
+
+#define        list_for_each_entry(VAR, HEAD, FIELD)                           
\
+       for ((VAR) = list_entry(list_first((HEAD)), typeof(*(VAR)), FIELD); \
+               &(VAR)->FIELD != (HEAD);                                \
+               (VAR) = list_entry(list_next(&(VAR)->FIELD), typeof(*(VAR)), \
+                   FIELD))
+
+#define        list_for_each_entry_reverse(VAR, HEAD, FIELD)                   
\
+       for ((VAR) = list_entry(list_last((HEAD)), typeof(*(VAR)), FIELD); \
+               &(VAR)->FIELD != (HEAD);                                \
+               (VAR) = list_entry(list_prev(&(VAR)->FIELD), typeof(*(VAR)), \
+                   FIELD))
+
+#define        list_for_each_entry_safe(VAR, NEXT, HEAD, FIELD)                
\
+       for ((VAR) = list_entry(list_first((HEAD)), typeof(*(VAR)), FIELD); \
+               (&(VAR)->FIELD != (HEAD)) &&                            \
+                   ((NEXT) = list_entry(list_next(&(VAR)->FIELD),      \
+                       typeof(*(VAR)), FIELD), 1);                     \
+               (VAR) = (NEXT))
+
+#define        list_for_each_entry_continue(VAR, HEAD, FIELD)                  
\
+       for ((VAR) = list_next_entry((VAR), FIELD);                     \
+               &(VAR)->FIELD != (HEAD);                                \
+               (VAR) = list_next_entry((VAR), FIELD))
+
+#define        list_for_each_entry_continue_reverse(VAR, HEAD, FIELD)          
\
+       for ((VAR) = list_prev_entry((VAR), FIELD);                     \
+               &(VAR)->FIELD != (HEAD);                                \
+               (VAR) = list_prev_entry((VAR), FIELD))
+
+#define        list_for_each_entry_safe_from(VAR, NEXT, HEAD, FIELD)           
\
+       for (;                                                          \
+               (&(VAR)->FIELD != (HEAD)) &&                            \
+                   ((NEXT) = list_next_entry((VAR), FIELD));           \
+               (VAR) = (NEXT))
+
+#endif  /* _LINUX_LIST_H_ */

Added: head/sys/contrib/vchiq/interface/compat/vchi_bsd.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/contrib/vchiq/interface/compat/vchi_bsd.c  Thu Feb  5 19:54:03 
2015        (r278277)
@@ -0,0 +1,532 @@
+/*-
+ * Copyright (c) 2010 Max Khon <[email protected]>
+ * All rights reserved.
+ *
+ * This software was developed by Max Khon under sponsorship from
+ * the FreeBSD Foundation and Ethon Technologies GmbH.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: bsd-compat.c 9253 2010-09-02 10:12:09Z fjoe $
+ */
+
+#include <sys/types.h>
+#include <sys/limits.h>
+#include <sys/bus.h>
+#include <sys/callout.h>
+#include <sys/firmware.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/syscallsubr.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/stdarg.h>
+
+#include "mbox_if.h"
+
+#include <interface/compat/vchi_bsd.h>
+
+MALLOC_DEFINE(M_VCHI, "VCHI", "VCHI");
+
+/*
+ * Timer API
+ */
+static void
+run_timer(void *arg)
+{
+       struct timer_list *t = (struct timer_list *) arg;
+       void (*function)(unsigned long);
+
+       mtx_lock_spin(&t->mtx);
+       if (callout_pending(&t->callout)) {
+               /* callout was reset */
+               mtx_unlock_spin(&t->mtx);
+               return;
+       }
+       if (!callout_active(&t->callout)) {
+               /* callout was stopped */
+               mtx_unlock_spin(&t->mtx);
+               return;
+       }
+       callout_deactivate(&t->callout);
+
+       function = t->function;
+       mtx_unlock_spin(&t->mtx);
+
+       function(t->data);
+}
+
+void
+init_timer(struct timer_list *t)
+{
+       mtx_init(&t->mtx, "dahdi timer lock", NULL, MTX_SPIN);
+       callout_init(&t->callout, CALLOUT_MPSAFE);
+       t->expires = 0;
+       /*
+        * function and data are not initialized intentionally:
+        * they are not initialized by Linux implementation too
+        */
+}
+
+void
+setup_timer(struct timer_list *t, void (*function)(unsigned long), unsigned 
long data)
+{
+       t->function = function;
+       t->data = data;
+       init_timer(t);
+}
+
+void
+mod_timer(struct timer_list *t, unsigned long expires)
+{
+       mtx_lock_spin(&t->mtx);
+       callout_reset(&t->callout, expires - jiffies, run_timer, t);
+       mtx_unlock_spin(&t->mtx);
+}
+
+void
+add_timer(struct timer_list *t)
+{
+       mod_timer(t, t->expires);
+}
+
+int
+del_timer_sync(struct timer_list *t)
+{
+       mtx_lock_spin(&t->mtx);
+       callout_stop(&t->callout);
+       mtx_unlock_spin(&t->mtx);
+
+       mtx_destroy(&t->mtx);
+       return 0;
+}
+
+int
+del_timer(struct timer_list *t)
+{
+       del_timer_sync(t);
+       return 0;
+}
+
+/*
+ * Completion API
+ */
+void
+init_completion(struct completion *c)
+{
+       cv_init(&c->cv, "VCHI completion cv");
+       mtx_init(&c->lock, "VCHI completion lock", "condvar", MTX_DEF);
+       c->done = 0;
+}
+
+void
+destroy_completion(struct completion *c)
+{
+       cv_destroy(&c->cv);
+       mtx_destroy(&c->lock);
+}
+
+void
+complete(struct completion *c)
+{
+       mtx_lock(&c->lock);
+
+       if (c->done >= 0) {
+               KASSERT(c->done < INT_MAX, ("c->done overflow")); /* XXX check 
*/
+               c->done++;
+               cv_signal(&c->cv);
+       } else {
+               KASSERT(c->done == -1, ("Invalid value of c->done: %d", 
c->done));
+       }
+
+       mtx_unlock(&c->lock);
+}
+
+void
+complete_all(struct completion *c)
+{
+       mtx_lock(&c->lock);
+
+       if (c->done >= 0) {
+               KASSERT(c->done < INT_MAX, ("c->done overflow")); /* XXX check 
*/
+               c->done = -1;
+               cv_broadcast(&c->cv);
+       } else {
+               KASSERT(c->done == -1, ("Invalid value of c->done: %d", 
c->done));
+       }
+
+       mtx_unlock(&c->lock);
+}
+
+void
+INIT_COMPLETION_locked(struct completion *c)
+{
+       mtx_lock(&c->lock);
+
+       c->done = 0;
+
+       mtx_unlock(&c->lock);
+}
+
+static void
+_completion_claim(struct completion *c)
+{
+
+       KASSERT(mtx_owned(&c->lock),
+           ("_completion_claim should be called with acquired lock"));
+       KASSERT(c->done != 0, ("_completion_claim on non-waited completion"));
+       if (c->done > 0)
+               c->done--;
+       else
+               KASSERT(c->done == -1, ("Invalid value of c->done: %d", 
c->done));
+}
+
+void
+wait_for_completion(struct completion *c)
+{
+       mtx_lock(&c->lock);
+       if (!c->done)
+               cv_wait(&c->cv, &c->lock);
+       c->done--;
+       mtx_unlock(&c->lock);
+}
+
+int
+try_wait_for_completion(struct completion *c)
+{
+       int res = 0;
+
+       mtx_lock(&c->lock);
+       if (!c->done)
+               res = 1;
+       else
+               c->done--;
+       mtx_unlock(&c->lock);
+       return res == 0;
+}
+
+int
+wait_for_completion_interruptible_timeout(struct completion *c, unsigned long 
timeout)
+{
+       int res = 0;
+       unsigned long start, now;
+       start = jiffies;
+
+       mtx_lock(&c->lock);
+       while (c->done == 0) {
+               res = cv_timedwait_sig(&c->cv, &c->lock, timeout);
+               if (res)
+                       goto out;
+               now = jiffies;
+               if (timeout < (now - start)) {
+                       res = EWOULDBLOCK;
+                       goto out;
+               }
+
+               timeout -= (now - start);
+               start = now;
+       }
+
+       _completion_claim(c);
+       res = 0;
+
+out:
+       mtx_unlock(&c->lock);
+
+       if (res == EWOULDBLOCK) {
+               return 0;
+       } else if ((res == EINTR) || (res == ERESTART)) {
+               return -ERESTART;
+       } else {
+               KASSERT((res == 0), ("res = %d", res));
+               return timeout;
+       }
+}
+
+int
+wait_for_completion_interruptible(struct completion *c)
+{
+       int res = 0;
+
+       mtx_lock(&c->lock);
+       while (c->done == 0) {
+               res = cv_wait_sig(&c->cv, &c->lock);
+               if (res)
+                       goto out;
+       }
+
+       _completion_claim(c);
+
+out:
+       mtx_unlock(&c->lock);
+
+       if ((res == EINTR) || (res == ERESTART))
+               res = -ERESTART;
+       return res;
+}
+
+int
+wait_for_completion_killable(struct completion *c)
+{
+
+       return wait_for_completion_interruptible(c);
+}
+
+/*
+ * Semaphore API
+ */
+
+void sema_sysinit(void *arg)
+{
+       struct semaphore *s = arg;
+
+       printf("sema_sysinit\n");
+       _sema_init(s, 1);
+}
+
+void
+_sema_init(struct semaphore *s, int value)
+{
+       bzero(s, sizeof(*s));
+       mtx_init(&s->mtx, "sema lock", "VCHIQ sepmaphore backing lock",
+               MTX_DEF | MTX_NOWITNESS | MTX_QUIET);
+       cv_init(&s->cv, "sema cv");
+       s->value = value;
+}
+
+void
+_sema_destroy(struct semaphore *s)
+{
+       mtx_destroy(&s->mtx);
+       cv_destroy(&s->cv);
+}
+
+void
+down(struct semaphore *s)
+{
+
+       mtx_lock(&s->mtx);
+       while (s->value == 0) {
+               s->waiters++;
+               cv_wait(&s->cv, &s->mtx);
+               s->waiters--;
+       }
+
+       s->value--;
+       mtx_unlock(&s->mtx);
+}
+
+int
+down_interruptible(struct semaphore *s)
+{
+       int ret ;
+
+       ret = 0;
+
+       mtx_lock(&s->mtx);
+
+       while (s->value == 0) {
+               s->waiters++;
+               ret = cv_wait_sig(&s->cv, &s->mtx);
+               s->waiters--;
+
+               if (ret == EINTR) {
+                       mtx_unlock(&s->mtx);
+                       return (-EINTR);
+               }
+
+               if (ret == ERESTART)
+                       continue;
+       }
+
+       s->value--;
+       mtx_unlock(&s->mtx);
+
+       return (0);
+}
+
+int
+down_trylock(struct semaphore *s)
+{
+       int ret;
+
+       ret = 0;
+
+       mtx_lock(&s->mtx);
+
+       if (s->value > 0) {
+               /* Success. */
+               s->value--;
+               ret = 0;
+       } else {
+               ret = -EAGAIN;
+       }
+
+       mtx_unlock(&s->mtx);
+
+       return (ret);
+}
+
+void
+up(struct semaphore *s)
+{
+       mtx_lock(&s->mtx);
+       s->value++;
+       if (s->waiters && s->value > 0)
+               cv_signal(&s->cv);
+
+       mtx_unlock(&s->mtx);
+}
+
+/*
+ * Logging API
+ */
+void
+rlprintf(int pps, const char *fmt, ...)
+{
+       va_list ap;
+       static struct timeval last_printf;
+       static int count;
+
+       if (ppsratecheck(&last_printf, &count, pps)) {
+               va_start(ap, fmt);
+               vprintf(fmt, ap);
+               va_end(ap);
+       }
+}
+
+void
+device_rlprintf(int pps, device_t dev, const char *fmt, ...)
+{
+       va_list ap;
+       static struct timeval last_printf;
+       static int count;
+
+       if (ppsratecheck(&last_printf, &count, pps)) {
+               va_start(ap, fmt);
+               device_print_prettyname(dev);
+               vprintf(fmt, ap);
+               va_end(ap);
+       }
+}
+
+/*
+ * Signals API
+ */
+
+void
+flush_signals(VCHIQ_THREAD_T thr)
+{
+       printf("Implement ME: %s\n", __func__);
+}
+
+int
+fatal_signal_pending(VCHIQ_THREAD_T thr)
+{
+       printf("Implement ME: %s\n", __func__);
+       return (0);
+}
+
+/*
+ * kthread API
+ */
+
+/*
+ *  This is a hack to avoid memory leak
+ */
+#define MAX_THREAD_DATA_SLOTS  32
+static int thread_data_slot = 0;
+
+struct thread_data {
+       void *data;
+       int (*threadfn)(void *);
+};
+
+static struct thread_data thread_slots[MAX_THREAD_DATA_SLOTS];
+
+static void
+kthread_wrapper(void *data)
+{
+       struct thread_data *slot;
+
+       slot = data;
+       slot->threadfn(slot->data);
+}
+
+VCHIQ_THREAD_T
+vchiq_thread_create(int (*threadfn)(void *data),
+       void *data,
+       const char namefmt[], ...)
+{
+       VCHIQ_THREAD_T newp;
+       va_list ap;
+       char name[MAXCOMLEN+1];
+       struct thread_data *slot;
+
+       if (thread_data_slot >= MAX_THREAD_DATA_SLOTS) {
+               printf("kthread_create: out of thread data slots\n");
+               return (NULL);
+       }
+
+       slot = &thread_slots[thread_data_slot];
+       slot->data = data;
+       slot->threadfn = threadfn;
+
+       va_start(ap, namefmt);
+       vsnprintf(name, sizeof(name), namefmt, ap);
+       va_end(ap);
+       
+       newp = NULL;
+       if (kproc_create(kthread_wrapper, (void*)slot, &newp, 0, 0,
+           "%s", name) != 0) {
+               /* Just to be sure */
+               newp = NULL;
+       }
+       else
+               thread_data_slot++;
+
+       return newp;
+}
+
+void
+set_user_nice(VCHIQ_THREAD_T thr, int nice)
+{
+       /* NOOP */
+}
+
+void
+wake_up_process(VCHIQ_THREAD_T thr)
+{
+       /* NOOP */
+}
+
+void
+bcm_mbox_write(int channel, uint32_t data)
+{
+       device_t mbox;
+
+        mbox = devclass_get_device(devclass_find("mbox"), 0);
+
+        if (mbox)
+                MBOX_WRITE(mbox, channel, data);
+}

Added: head/sys/contrib/vchiq/interface/compat/vchi_bsd.h
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/contrib/vchiq/interface/compat/vchi_bsd.h  Thu Feb  5 19:54:03 
2015        (r278277)
@@ -0,0 +1,434 @@
+/*-
+ * Copyright (c) 2010 Max Khon <[email protected]>
+ * Copyright (c) 2012 Oleksandr Tymoshenko <[email protected]>
+ * Copyright (c) 2013 Jared D. McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef __VCHI_BSD_H__
+#define __VCHI_BSD_H__
+
+#include <sys/systm.h>
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/lock.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
+#include <sys/sema.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/types.h>
+#include <sys/ioccom.h>
+
+/*
+ * Copy from/to user API
+ */
+#define copy_from_user(to, from, n)    copyin((from), (to), (n))
+#define copy_to_user(to, from, n)      copyout((from), (to), (n))
+
+/*
+ * Bit API
+ */
+
+static __inline int
+test_and_set_bit(int nr, volatile void *addr)
+{
+       int val;
+
+       do {
+               val = *(volatile int *) addr;
+       } while (atomic_cmpset_int(addr, val, val | (1 << nr)) == 0);
+       return (val & (1 << nr));
+}
+
+static __inline__
+int test_and_clear_bit(int nr, volatile void *addr)
+{
+       int val;
+
+       do {
+               val = *(volatile int *) addr;
+       } while (atomic_cmpset_int(addr, val, val & ~(1 << nr)) == 0);
+       return (val & (1 << nr));
+}
+
+/*
+ * Atomic API
+ */
+typedef volatile unsigned atomic_t;
+
+#define atomic_set(p, v)       (*(p) = (v))
+#define atomic_read(p)         (*(p))
+#define atomic_inc(p)          atomic_add_int(p, 1)
+#define atomic_dec(p)          atomic_subtract_int(p, 1)
+#define atomic_dec_and_test(p) (atomic_fetchadd_int(p, -1) == 1)
+#define        atomic_inc_return(v)    atomic_add_return(1, (v))
+#define        atomic_dec_return(v)    atomic_sub_return(1, (v))
+#define atomic_add(v, p)       atomic_add_int(p, v)
+#define atomic_sub(v, p)       atomic_subtract_int(p, v)
+
+#define ATOMIC_INIT(v)         (v)
+
+static inline int
+atomic_add_return(int i, atomic_t *v)
+{
+       return i + atomic_fetchadd_int(v, i);
+}
+
+static inline int
+atomic_sub_return(int i, atomic_t *v)
+{
+       return atomic_fetchadd_int(v, -i) - i;
+}
+
+static inline int
+atomic_cmpxchg(atomic_t *v, int oldv, int newv)
+{
+       if (atomic_cmpset_rel_int(v, oldv, newv))
+               return newv;
+       else
+               return *v;
+}
+
+static inline int
+atomic_xchg(atomic_t *v, int newv)
+{
+       int oldv;
+       if (newv == 0)
+               return atomic_readandclear_int(v);
+       else {
+               do {
+                       oldv = atomic_load_acq_int(v);
+               } while (!atomic_cmpset_rel_int(v, oldv, newv));
+       }
+
+       return (oldv);
+}
+
+/*
+ * Spinlock API
+ */
+typedef struct mtx spinlock_t;
+
+#define DEFINE_SPINLOCK(name)                          \
+       struct mtx name
+#define spin_lock_init(lock)   mtx_init(lock, "VCHI spinlock " # lock, NULL, 
MTX_DEF)
+#define spin_lock_destroy(lock)        mtx_destroy(lock)
+#define spin_lock(lock)                mtx_lock(lock)
+#define spin_unlock(lock)      mtx_unlock(lock)
+#define spin_lock_bh(lock)     spin_lock(lock)
+#define spin_unlock_bh(lock)   spin_unlock(lock)
+
+/*
+ * Mutex API
+ */
+struct mutex {
+       struct mtx      mtx;
+};
+
+#define        lmutex_init(lock)       mtx_init(&(lock)->mtx, #lock, NULL, 
MTX_DEF)
+#define lmutex_lock(lock)      mtx_lock(&(lock)->mtx)
+#define        lmutex_lock_interruptible(lock) (mtx_lock(&(lock)->mtx),0)
+#define        lmutex_unlock(lock)     mtx_unlock(&(lock)->mtx)
+#define        lmutex_destroy(lock)    mtx_destroy(&(lock)->mtx)
+
+/*
+ * Rwlock API
+ */
+typedef struct sx rwlock_t;
+
+#if defined(SX_ADAPTIVESPIN) && !defined(SX_NOADAPTIVE)
+#define SX_NOADAPTIVE SX_ADAPTIVESPIN
+#endif

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to