Import VCHI driver for Broadcom's VideoCore IV GPU
Differential Revision: D1753
This commit is contained in:
parent
bae1c14d6b
commit
262f27b29e
@ -27,3 +27,23 @@ kern/kern_clocksource.c standard
|
||||
|
||||
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"
|
||||
|
@ -79,6 +79,9 @@ INCLUDES+= -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal
|
||||
# ... 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
|
||||
|
||||
|
256
sys/contrib/vchiq/interface/compat/list.h
Normal file
256
sys/contrib/vchiq/interface/compat/list.h
Normal file
@ -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_ */
|
532
sys/contrib/vchiq/interface/compat/vchi_bsd.c
Normal file
532
sys/contrib/vchiq/interface/compat/vchi_bsd.c
Normal file
@ -0,0 +1,532 @@
|
||||
/*-
|
||||
* Copyright (c) 2010 Max Khon <fjoe@freebsd.org>
|
||||
* 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);
|
||||
}
|
434
sys/contrib/vchiq/interface/compat/vchi_bsd.h
Normal file
434
sys/contrib/vchiq/interface/compat/vchi_bsd.h
Normal file
@ -0,0 +1,434 @@
|
||||
/*-
|
||||
* Copyright (c) 2010 Max Khon <fjoe@freebsd.org>
|
||||
* Copyright (c) 2012 Oleksandr Tymoshenko <gonzo@bluezbox.com>
|
||||
* Copyright (c) 2013 Jared D. McNeill <jmcneill@invisible.ca>
|
||||
* 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
|
||||
|
||||
#define DEFINE_RWLOCK(name) \
|
||||
struct sx name; \
|
||||
SX_SYSINIT(name, &name, #name)
|
||||
#define rwlock_init(rwlock) sx_init_flags(rwlock, "VCHI rwlock", SX_NOADAPTIVE)
|
||||
#define read_lock(rwlock) sx_slock(rwlock)
|
||||
#define read_unlock(rwlock) sx_sunlock(rwlock)
|
||||
|
||||
#define write_lock(rwlock) sx_xlock(rwlock)
|
||||
#define write_unlock(rwlock) sx_xunlock(rwlock)
|
||||
#define write_lock_irqsave(rwlock, flags) \
|
||||
do { \
|
||||
sx_xlock(rwlock); \
|
||||
(void) &(flags); \
|
||||
} while (0)
|
||||
#define write_unlock_irqrestore(rwlock, flags) \
|
||||
sx_xunlock(rwlock)
|
||||
|
||||
#define read_lock_bh(rwlock) sx_slock(rwlock)
|
||||
#define read_unlock_bh(rwlock) sx_sunlock(rwlock)
|
||||
#define write_lock_bh(rwlock) sx_xlock(rwlock)
|
||||
#define write_unlock_bh(rwlock) sx_xunlock(rwlock)
|
||||
|
||||
/*
|
||||
* Timer API
|
||||
*/
|
||||
struct timer_list {
|
||||
struct mtx mtx;
|
||||
struct callout callout;
|
||||
|
||||
unsigned long expires;
|
||||
void (*function)(unsigned long);
|
||||
unsigned long data;
|
||||
};
|
||||
|
||||
void init_timer(struct timer_list *t);
|
||||
void setup_timer(struct timer_list *t, void (*function)(unsigned long), unsigned long data);
|
||||
void mod_timer(struct timer_list *t, unsigned long expires);
|
||||
void add_timer(struct timer_list *t);
|
||||
int del_timer(struct timer_list *t);
|
||||
int del_timer_sync(struct timer_list *t);
|
||||
|
||||
/*
|
||||
* Completion API
|
||||
*/
|
||||
struct completion {
|
||||
struct cv cv;
|
||||
struct mtx lock;
|
||||
int done;
|
||||
};
|
||||
|
||||
void init_completion(struct completion *c);
|
||||
void destroy_completion(struct completion *c);
|
||||
int try_wait_for_completion(struct completion *);
|
||||
int wait_for_completion_interruptible(struct completion *);
|
||||
int wait_for_completion_interruptible_timeout(struct completion *, unsigned long ticks);
|
||||
int wait_for_completion_killable(struct completion *);
|
||||
void wait_for_completion(struct completion *c);
|
||||
void complete(struct completion *c);
|
||||
void complete_all(struct completion *c);
|
||||
void INIT_COMPLETION_locked(struct completion *c);
|
||||
|
||||
#define INIT_COMPLETION(x) INIT_COMPLETION_locked(&(x))
|
||||
|
||||
/*
|
||||
* Semaphore API
|
||||
*/
|
||||
struct semaphore {
|
||||
struct mtx mtx;
|
||||
struct cv cv;
|
||||
int value;
|
||||
int waiters;
|
||||
};
|
||||
|
||||
#define DEFINE_SEMAPHORE(name) \
|
||||
struct semaphore name; \
|
||||
SYSINIT(name##_sema_sysinit, SI_SUB_LOCK, SI_ORDER_MIDDLE, \
|
||||
sema_sysinit, &name); \
|
||||
SYSUNINIT(name##_sema_sysuninit, SI_SUB_LOCK, SI_ORDER_MIDDLE, \
|
||||
_sema_destroy, __DEVOLATILE(void *, &(name)))
|
||||
|
||||
void sema_sysinit(void *arg);
|
||||
void _sema_init(struct semaphore *s, int value);
|
||||
void _sema_destroy(struct semaphore *s);
|
||||
void down(struct semaphore *s);
|
||||
int down_interruptible(struct semaphore *s);
|
||||
int down_trylock(struct semaphore *s);
|
||||
void up(struct semaphore *s);
|
||||
|
||||
/*
|
||||
* Logging and assertions API
|
||||
*/
|
||||
void rlprintf(int pps, const char *fmt, ...)
|
||||
__printflike(2, 3);
|
||||
|
||||
void
|
||||
device_rlprintf(int pps, device_t dev, const char *fmt, ...)
|
||||
__printflike(3, 4);
|
||||
|
||||
#define might_sleep()
|
||||
|
||||
#define WARN(condition, msg) \
|
||||
({ \
|
||||
int __ret_warn_on = !!(condition); \
|
||||
if (unlikely(__ret_warn_on)) \
|
||||
printf((msg)); \
|
||||
unlikely(__ret_warn_on); \
|
||||
})
|
||||
|
||||
|
||||
|
||||
#define WARN_ON(condition) \
|
||||
({ \
|
||||
int __ret_warn_on = !!(condition); \
|
||||
if (unlikely(__ret_warn_on)) \
|
||||
printf("WARN_ON: " #condition "\n"); \
|
||||
unlikely(__ret_warn_on); \
|
||||
})
|
||||
|
||||
#define WARN_ON_ONCE(condition) ({ \
|
||||
static int __warned; \
|
||||
int __ret_warn_once = !!(condition); \
|
||||
\
|
||||
if (unlikely(__ret_warn_once)) \
|
||||
if (WARN_ON(!__warned)) \
|
||||
__warned = 1; \
|
||||
unlikely(__ret_warn_once); \
|
||||
})
|
||||
|
||||
#define BUG_ON(cond) \
|
||||
do { \
|
||||
if (cond) \
|
||||
panic("BUG_ON: " #cond); \
|
||||
} while (0)
|
||||
|
||||
#define BUG() \
|
||||
do { \
|
||||
panic("BUG: %s:%d", __FILE__, __LINE__); \
|
||||
} while (0)
|
||||
|
||||
#define vchiq_static_assert(cond) CTASSERT(cond)
|
||||
|
||||
#define KERN_EMERG "<0>" /* system is unusable */
|
||||
#define KERN_ALERT "<1>" /* action must be taken immediately */
|
||||
#define KERN_CRIT "<2>" /* critical conditions */
|
||||
#define KERN_ERR "<3>" /* error conditions */
|
||||
#define KERN_WARNING "<4>" /* warning conditions */
|
||||
#define KERN_NOTICE "<5>" /* normal but significant condition */
|
||||
#define KERN_INFO "<6>" /* informational */
|
||||
#define KERN_DEBUG "<7>" /* debug-level messages */
|
||||
#define KERN_CONT ""
|
||||
|
||||
#define printk(fmt, args...) printf(fmt, ##args)
|
||||
#define vprintk(fmt, args) vprintf(fmt, args)
|
||||
|
||||
/*
|
||||
* Malloc API
|
||||
*/
|
||||
#define GFP_KERNEL 0
|
||||
#define GFP_ATOMIC 0
|
||||
|
||||
MALLOC_DECLARE(M_VCHI);
|
||||
|
||||
#define kmalloc(size, flags) malloc((size), M_VCHI, M_NOWAIT | M_ZERO)
|
||||
#define kcalloc(n, size, flags) malloc((n) * (size), M_VCHI, M_NOWAIT | M_ZERO)
|
||||
#define kzalloc(a, b) kcalloc(1, (a), (b))
|
||||
#define kfree(p) free(p, M_VCHI)
|
||||
|
||||
/*
|
||||
* Kernel module API
|
||||
*/
|
||||
#define __init
|
||||
#define __exit
|
||||
#define __devinit
|
||||
#define __devexit
|
||||
#define __devinitdata
|
||||
|
||||
/*
|
||||
* Time API
|
||||
*/
|
||||
#if 1
|
||||
/* emulate jiffies */
|
||||
static inline unsigned long
|
||||
_jiffies(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
microuptime(&tv);
|
||||
return tvtohz(&tv);
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
msecs_to_jiffies(unsigned long msecs)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
tv.tv_sec = msecs / 1000000UL;
|
||||
tv.tv_usec = msecs % 1000000UL;
|
||||
return tvtohz(&tv);
|
||||
}
|
||||
|
||||
#define jiffies _jiffies()
|
||||
#else
|
||||
#define jiffies ticks
|
||||
#endif
|
||||
#define HZ hz
|
||||
|
||||
#define udelay(usec) DELAY(usec)
|
||||
#define mdelay(msec) DELAY((msec) * 1000)
|
||||
|
||||
#define schedule_timeout(jiff) pause("dhdslp", jiff)
|
||||
|
||||
#if defined(msleep)
|
||||
#undef msleep
|
||||
#endif
|
||||
#define msleep(msec) mdelay(msec)
|
||||
|
||||
#define time_after(a, b) ((a) > (b))
|
||||
#define time_after_eq(a, b) ((a) >= (b))
|
||||
#define time_before(a, b) time_after((b), (a))
|
||||
|
||||
/*
|
||||
* kthread API (we use proc)
|
||||
*/
|
||||
typedef struct proc * VCHIQ_THREAD_T;
|
||||
|
||||
VCHIQ_THREAD_T vchiq_thread_create(int (*threadfn)(void *data),
|
||||
void *data,
|
||||
const char namefmt[], ...);
|
||||
void set_user_nice(VCHIQ_THREAD_T p, int nice);
|
||||
void wake_up_process(VCHIQ_THREAD_T p);
|
||||
|
||||
/*
|
||||
* Proc APIs
|
||||
*/
|
||||
void flush_signals(VCHIQ_THREAD_T);
|
||||
int fatal_signal_pending(VCHIQ_THREAD_T);
|
||||
|
||||
/*
|
||||
* mbox API
|
||||
*/
|
||||
void bcm_mbox_write(int channel, uint32_t data);
|
||||
|
||||
/*
|
||||
* Misc API
|
||||
*/
|
||||
|
||||
#define ENODATA EINVAL
|
||||
|
||||
#define __user
|
||||
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#define current curproc
|
||||
#define EXPORT_SYMBOL(x)
|
||||
#define PAGE_ALIGN(addr) round_page(addr)
|
||||
|
||||
typedef void irqreturn_t;
|
||||
typedef off_t loff_t;
|
||||
|
||||
#define BCM2835_MBOX_CHAN_VCHIQ 3
|
||||
|
||||
#define smp_mb wmb
|
||||
#define smp_rmb rmb
|
||||
#define smp_wmb wmb
|
||||
|
||||
#define device_print_prettyname(dev) device_printf((dev), "")
|
||||
|
||||
#endif /* __VCHI_BSD_H__ */
|
324
sys/contrib/vchiq/interface/vchi/connections/connection.h
Normal file
324
sys/contrib/vchiq/interface/vchi/connections/connection.h
Normal file
@ -0,0 +1,324 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CONNECTION_H_
|
||||
#define CONNECTION_H_
|
||||
|
||||
#include "interface/vchi/vchi_cfg_internal.h"
|
||||
#include "interface/vchi/vchi_common.h"
|
||||
#include "interface/vchi/message_drivers/message.h"
|
||||
|
||||
/******************************************************************************
|
||||
Global defs
|
||||
*****************************************************************************/
|
||||
|
||||
// Opaque handle for a connection / service pair
|
||||
typedef struct opaque_vchi_connection_connected_service_handle_t *VCHI_CONNECTION_SERVICE_HANDLE_T;
|
||||
|
||||
// opaque handle to the connection state information
|
||||
typedef struct opaque_vchi_connection_info_t VCHI_CONNECTION_STATE_T;
|
||||
|
||||
typedef struct vchi_connection_t VCHI_CONNECTION_T;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
API
|
||||
*****************************************************************************/
|
||||
|
||||
// Routine to init a connection with a particular low level driver
|
||||
typedef VCHI_CONNECTION_STATE_T * (*VCHI_CONNECTION_INIT_T)( struct vchi_connection_t * connection,
|
||||
const VCHI_MESSAGE_DRIVER_T * driver );
|
||||
|
||||
// Routine to control CRC enabling at a connection level
|
||||
typedef int32_t (*VCHI_CONNECTION_CRC_CONTROL_T)( VCHI_CONNECTION_STATE_T *state_handle,
|
||||
VCHI_CRC_CONTROL_T control );
|
||||
|
||||
// Routine to create a service
|
||||
typedef int32_t (*VCHI_CONNECTION_SERVICE_CONNECT_T)( VCHI_CONNECTION_STATE_T *state_handle,
|
||||
int32_t service_id,
|
||||
uint32_t rx_fifo_size,
|
||||
uint32_t tx_fifo_size,
|
||||
int server,
|
||||
VCHI_CALLBACK_T callback,
|
||||
void *callback_param,
|
||||
int32_t want_crc,
|
||||
int32_t want_unaligned_bulk_rx,
|
||||
int32_t want_unaligned_bulk_tx,
|
||||
VCHI_CONNECTION_SERVICE_HANDLE_T *service_handle );
|
||||
|
||||
// Routine to close a service
|
||||
typedef int32_t (*VCHI_CONNECTION_SERVICE_DISCONNECT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle );
|
||||
|
||||
// Routine to queue a message
|
||||
typedef int32_t (*VCHI_CONNECTION_SERVICE_QUEUE_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
const void *data,
|
||||
uint32_t data_size,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *msg_handle );
|
||||
|
||||
// scatter-gather (vector) message queueing
|
||||
typedef int32_t (*VCHI_CONNECTION_SERVICE_QUEUE_MESSAGEV_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
VCHI_MSG_VECTOR_T *vector,
|
||||
uint32_t count,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *msg_handle );
|
||||
|
||||
// Routine to dequeue a message
|
||||
typedef int32_t (*VCHI_CONNECTION_SERVICE_DEQUEUE_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
void *data,
|
||||
uint32_t max_data_size_to_read,
|
||||
uint32_t *actual_msg_size,
|
||||
VCHI_FLAGS_T flags );
|
||||
|
||||
// Routine to peek at a message
|
||||
typedef int32_t (*VCHI_CONNECTION_SERVICE_PEEK_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
void **data,
|
||||
uint32_t *msg_size,
|
||||
VCHI_FLAGS_T flags );
|
||||
|
||||
// Routine to hold a message
|
||||
typedef int32_t (*VCHI_CONNECTION_SERVICE_HOLD_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
void **data,
|
||||
uint32_t *msg_size,
|
||||
VCHI_FLAGS_T flags,
|
||||
void **message_handle );
|
||||
|
||||
// Routine to initialise a received message iterator
|
||||
typedef int32_t (*VCHI_CONNECTION_SERVICE_LOOKAHEAD_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
VCHI_MSG_ITER_T *iter,
|
||||
VCHI_FLAGS_T flags );
|
||||
|
||||
// Routine to release a held message
|
||||
typedef int32_t (*VCHI_CONNECTION_HELD_MSG_RELEASE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
void *message_handle );
|
||||
|
||||
// Routine to get info on a held message
|
||||
typedef int32_t (*VCHI_CONNECTION_HELD_MSG_INFO_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
void *message_handle,
|
||||
void **data,
|
||||
int32_t *msg_size,
|
||||
uint32_t *tx_timestamp,
|
||||
uint32_t *rx_timestamp );
|
||||
|
||||
// Routine to check whether the iterator has a next message
|
||||
typedef int32_t (*VCHI_CONNECTION_MSG_ITER_HAS_NEXT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service,
|
||||
const VCHI_MSG_ITER_T *iter );
|
||||
|
||||
// Routine to advance the iterator
|
||||
typedef int32_t (*VCHI_CONNECTION_MSG_ITER_NEXT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service,
|
||||
VCHI_MSG_ITER_T *iter,
|
||||
void **data,
|
||||
uint32_t *msg_size );
|
||||
|
||||
// Routine to remove the last message returned by the iterator
|
||||
typedef int32_t (*VCHI_CONNECTION_MSG_ITER_REMOVE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service,
|
||||
VCHI_MSG_ITER_T *iter );
|
||||
|
||||
// Routine to hold the last message returned by the iterator
|
||||
typedef int32_t (*VCHI_CONNECTION_MSG_ITER_HOLD_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service,
|
||||
VCHI_MSG_ITER_T *iter,
|
||||
void **msg_handle );
|
||||
|
||||
// Routine to transmit bulk data
|
||||
typedef int32_t (*VCHI_CONNECTION_BULK_QUEUE_TRANSMIT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
const void *data_src,
|
||||
uint32_t data_size,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *bulk_handle );
|
||||
|
||||
// Routine to receive data
|
||||
typedef int32_t (*VCHI_CONNECTION_BULK_QUEUE_RECEIVE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
void *data_dst,
|
||||
uint32_t data_size,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *bulk_handle );
|
||||
|
||||
// Routine to report if a server is available
|
||||
typedef int32_t (*VCHI_CONNECTION_SERVER_PRESENT)( VCHI_CONNECTION_STATE_T *state, int32_t service_id, int32_t peer_flags );
|
||||
|
||||
// Routine to report the number of RX slots available
|
||||
typedef int (*VCHI_CONNECTION_RX_SLOTS_AVAILABLE)( const VCHI_CONNECTION_STATE_T *state );
|
||||
|
||||
// Routine to report the RX slot size
|
||||
typedef uint32_t (*VCHI_CONNECTION_RX_SLOT_SIZE)( const VCHI_CONNECTION_STATE_T *state );
|
||||
|
||||
// Callback to indicate that the other side has added a buffer to the rx bulk DMA FIFO
|
||||
typedef void (*VCHI_CONNECTION_RX_BULK_BUFFER_ADDED)(VCHI_CONNECTION_STATE_T *state,
|
||||
int32_t service,
|
||||
uint32_t length,
|
||||
MESSAGE_TX_CHANNEL_T channel,
|
||||
uint32_t channel_params,
|
||||
uint32_t data_length,
|
||||
uint32_t data_offset);
|
||||
|
||||
// Callback to inform a service that a Xon or Xoff message has been received
|
||||
typedef void (*VCHI_CONNECTION_FLOW_CONTROL)(VCHI_CONNECTION_STATE_T *state, int32_t service_id, int32_t xoff);
|
||||
|
||||
// Callback to inform a service that a server available reply message has been received
|
||||
typedef void (*VCHI_CONNECTION_SERVER_AVAILABLE_REPLY)(VCHI_CONNECTION_STATE_T *state, int32_t service_id, uint32_t flags);
|
||||
|
||||
// Callback to indicate that bulk auxiliary messages have arrived
|
||||
typedef void (*VCHI_CONNECTION_BULK_AUX_RECEIVED)(VCHI_CONNECTION_STATE_T *state);
|
||||
|
||||
// Callback to indicate that bulk auxiliary messages have arrived
|
||||
typedef void (*VCHI_CONNECTION_BULK_AUX_TRANSMITTED)(VCHI_CONNECTION_STATE_T *state, void *handle);
|
||||
|
||||
// Callback with all the connection info you require
|
||||
typedef void (*VCHI_CONNECTION_INFO)(VCHI_CONNECTION_STATE_T *state, uint32_t protocol_version, uint32_t slot_size, uint32_t num_slots, uint32_t min_bulk_size);
|
||||
|
||||
// Callback to inform of a disconnect
|
||||
typedef void (*VCHI_CONNECTION_DISCONNECT)(VCHI_CONNECTION_STATE_T *state, uint32_t flags);
|
||||
|
||||
// Callback to inform of a power control request
|
||||
typedef void (*VCHI_CONNECTION_POWER_CONTROL)(VCHI_CONNECTION_STATE_T *state, MESSAGE_TX_CHANNEL_T channel, int32_t enable);
|
||||
|
||||
// allocate memory suitably aligned for this connection
|
||||
typedef void * (*VCHI_BUFFER_ALLOCATE)(VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, uint32_t * length);
|
||||
|
||||
// free memory allocated by buffer_allocate
|
||||
typedef void (*VCHI_BUFFER_FREE)(VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, void * address);
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
System driver struct
|
||||
*****************************************************************************/
|
||||
|
||||
struct opaque_vchi_connection_api_t
|
||||
{
|
||||
// Routine to init the connection
|
||||
VCHI_CONNECTION_INIT_T init;
|
||||
|
||||
// Connection-level CRC control
|
||||
VCHI_CONNECTION_CRC_CONTROL_T crc_control;
|
||||
|
||||
// Routine to connect to or create service
|
||||
VCHI_CONNECTION_SERVICE_CONNECT_T service_connect;
|
||||
|
||||
// Routine to disconnect from a service
|
||||
VCHI_CONNECTION_SERVICE_DISCONNECT_T service_disconnect;
|
||||
|
||||
// Routine to queue a message
|
||||
VCHI_CONNECTION_SERVICE_QUEUE_MESSAGE_T service_queue_msg;
|
||||
|
||||
// scatter-gather (vector) message queue
|
||||
VCHI_CONNECTION_SERVICE_QUEUE_MESSAGEV_T service_queue_msgv;
|
||||
|
||||
// Routine to dequeue a message
|
||||
VCHI_CONNECTION_SERVICE_DEQUEUE_MESSAGE_T service_dequeue_msg;
|
||||
|
||||
// Routine to peek at a message
|
||||
VCHI_CONNECTION_SERVICE_PEEK_MESSAGE_T service_peek_msg;
|
||||
|
||||
// Routine to hold a message
|
||||
VCHI_CONNECTION_SERVICE_HOLD_MESSAGE_T service_hold_msg;
|
||||
|
||||
// Routine to initialise a received message iterator
|
||||
VCHI_CONNECTION_SERVICE_LOOKAHEAD_MESSAGE_T service_look_ahead_msg;
|
||||
|
||||
// Routine to release a message
|
||||
VCHI_CONNECTION_HELD_MSG_RELEASE_T held_msg_release;
|
||||
|
||||
// Routine to get information on a held message
|
||||
VCHI_CONNECTION_HELD_MSG_INFO_T held_msg_info;
|
||||
|
||||
// Routine to check for next message on iterator
|
||||
VCHI_CONNECTION_MSG_ITER_HAS_NEXT_T msg_iter_has_next;
|
||||
|
||||
// Routine to get next message on iterator
|
||||
VCHI_CONNECTION_MSG_ITER_NEXT_T msg_iter_next;
|
||||
|
||||
// Routine to remove the last message returned by iterator
|
||||
VCHI_CONNECTION_MSG_ITER_REMOVE_T msg_iter_remove;
|
||||
|
||||
// Routine to hold the last message returned by iterator
|
||||
VCHI_CONNECTION_MSG_ITER_HOLD_T msg_iter_hold;
|
||||
|
||||
// Routine to transmit bulk data
|
||||
VCHI_CONNECTION_BULK_QUEUE_TRANSMIT_T bulk_queue_transmit;
|
||||
|
||||
// Routine to receive data
|
||||
VCHI_CONNECTION_BULK_QUEUE_RECEIVE_T bulk_queue_receive;
|
||||
|
||||
// Routine to report the available servers
|
||||
VCHI_CONNECTION_SERVER_PRESENT server_present;
|
||||
|
||||
// Routine to report the number of RX slots available
|
||||
VCHI_CONNECTION_RX_SLOTS_AVAILABLE connection_rx_slots_available;
|
||||
|
||||
// Routine to report the RX slot size
|
||||
VCHI_CONNECTION_RX_SLOT_SIZE connection_rx_slot_size;
|
||||
|
||||
// Callback to indicate that the other side has added a buffer to the rx bulk DMA FIFO
|
||||
VCHI_CONNECTION_RX_BULK_BUFFER_ADDED rx_bulk_buffer_added;
|
||||
|
||||
// Callback to inform a service that a Xon or Xoff message has been received
|
||||
VCHI_CONNECTION_FLOW_CONTROL flow_control;
|
||||
|
||||
// Callback to inform a service that a server available reply message has been received
|
||||
VCHI_CONNECTION_SERVER_AVAILABLE_REPLY server_available_reply;
|
||||
|
||||
// Callback to indicate that bulk auxiliary messages have arrived
|
||||
VCHI_CONNECTION_BULK_AUX_RECEIVED bulk_aux_received;
|
||||
|
||||
// Callback to indicate that a bulk auxiliary message has been transmitted
|
||||
VCHI_CONNECTION_BULK_AUX_TRANSMITTED bulk_aux_transmitted;
|
||||
|
||||
// Callback to provide information about the connection
|
||||
VCHI_CONNECTION_INFO connection_info;
|
||||
|
||||
// Callback to notify that peer has requested disconnect
|
||||
VCHI_CONNECTION_DISCONNECT disconnect;
|
||||
|
||||
// Callback to notify that peer has requested power change
|
||||
VCHI_CONNECTION_POWER_CONTROL power_control;
|
||||
|
||||
// allocate memory suitably aligned for this connection
|
||||
VCHI_BUFFER_ALLOCATE buffer_allocate;
|
||||
|
||||
// free memory allocated by buffer_allocate
|
||||
VCHI_BUFFER_FREE buffer_free;
|
||||
|
||||
};
|
||||
|
||||
struct vchi_connection_t {
|
||||
const VCHI_CONNECTION_API_T *api;
|
||||
VCHI_CONNECTION_STATE_T *state;
|
||||
#ifdef VCHI_COARSE_LOCKING
|
||||
struct semaphore sem;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#endif /* CONNECTION_H_ */
|
||||
|
||||
/****************************** End of file **********************************/
|
200
sys/contrib/vchiq/interface/vchi/message_drivers/message.h
Normal file
200
sys/contrib/vchiq/interface/vchi/message_drivers/message.h
Normal file
@ -0,0 +1,200 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _VCHI_MESSAGE_H_
|
||||
#define _VCHI_MESSAGE_H_
|
||||
|
||||
#include "interface/vchi/vchi_cfg_internal.h"
|
||||
#include "interface/vchi/vchi_common.h"
|
||||
|
||||
|
||||
typedef enum message_event_type {
|
||||
MESSAGE_EVENT_NONE,
|
||||
MESSAGE_EVENT_NOP,
|
||||
MESSAGE_EVENT_MESSAGE,
|
||||
MESSAGE_EVENT_SLOT_COMPLETE,
|
||||
MESSAGE_EVENT_RX_BULK_PAUSED,
|
||||
MESSAGE_EVENT_RX_BULK_COMPLETE,
|
||||
MESSAGE_EVENT_TX_COMPLETE,
|
||||
MESSAGE_EVENT_MSG_DISCARDED
|
||||
} MESSAGE_EVENT_TYPE_T;
|
||||
|
||||
typedef enum vchi_msg_flags
|
||||
{
|
||||
VCHI_MSG_FLAGS_NONE = 0x0,
|
||||
VCHI_MSG_FLAGS_TERMINATE_DMA = 0x1
|
||||
} VCHI_MSG_FLAGS_T;
|
||||
|
||||
typedef enum message_tx_channel
|
||||
{
|
||||
MESSAGE_TX_CHANNEL_MESSAGE = 0,
|
||||
MESSAGE_TX_CHANNEL_BULK = 1 // drivers may provide multiple bulk channels, from 1 upwards
|
||||
} MESSAGE_TX_CHANNEL_T;
|
||||
|
||||
// Macros used for cycling through bulk channels
|
||||
#define MESSAGE_TX_CHANNEL_BULK_PREV(c) (MESSAGE_TX_CHANNEL_BULK+((c)-MESSAGE_TX_CHANNEL_BULK+VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION-1)%VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION)
|
||||
#define MESSAGE_TX_CHANNEL_BULK_NEXT(c) (MESSAGE_TX_CHANNEL_BULK+((c)-MESSAGE_TX_CHANNEL_BULK+1)%VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION)
|
||||
|
||||
typedef enum message_rx_channel
|
||||
{
|
||||
MESSAGE_RX_CHANNEL_MESSAGE = 0,
|
||||
MESSAGE_RX_CHANNEL_BULK = 1 // drivers may provide multiple bulk channels, from 1 upwards
|
||||
} MESSAGE_RX_CHANNEL_T;
|
||||
|
||||
// Message receive slot information
|
||||
typedef struct rx_msg_slot_info {
|
||||
|
||||
struct rx_msg_slot_info *next;
|
||||
//struct slot_info *prev;
|
||||
#if !defined VCHI_COARSE_LOCKING
|
||||
struct semaphore sem;
|
||||
#endif
|
||||
|
||||
uint8_t *addr; // base address of slot
|
||||
uint32_t len; // length of slot in bytes
|
||||
|
||||
uint32_t write_ptr; // hardware causes this to advance
|
||||
uint32_t read_ptr; // this module does the reading
|
||||
int active; // is this slot in the hardware dma fifo?
|
||||
uint32_t msgs_parsed; // count how many messages are in this slot
|
||||
uint32_t msgs_released; // how many messages have been released
|
||||
void *state; // connection state information
|
||||
uint8_t ref_count[VCHI_MAX_SERVICES_PER_CONNECTION]; // reference count for slots held by services
|
||||
} RX_MSG_SLOTINFO_T;
|
||||
|
||||
// The message driver no longer needs to know about the fields of RX_BULK_SLOTINFO_T - sort this out.
|
||||
// In particular, it mustn't use addr and len - they're the client buffer, but the message
|
||||
// driver will be tasked with sending the aligned core section.
|
||||
typedef struct rx_bulk_slotinfo_t {
|
||||
struct rx_bulk_slotinfo_t *next;
|
||||
|
||||
struct semaphore *blocking;
|
||||
|
||||
// needed by DMA
|
||||
void *addr;
|
||||
uint32_t len;
|
||||
|
||||
// needed for the callback
|
||||
void *service;
|
||||
void *handle;
|
||||
VCHI_FLAGS_T flags;
|
||||
} RX_BULK_SLOTINFO_T;
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* each connection driver will have a pool of the following struct.
|
||||
*
|
||||
* the pool will be managed by vchi_qman_*
|
||||
* this means there will be multiple queues (single linked lists)
|
||||
* a given struct message_info will be on exactly one of these queues
|
||||
* at any one time
|
||||
* -------------------------------------------------------------------- */
|
||||
typedef struct rx_message_info {
|
||||
|
||||
struct message_info *next;
|
||||
//struct message_info *prev;
|
||||
|
||||
uint8_t *addr;
|
||||
uint32_t len;
|
||||
RX_MSG_SLOTINFO_T *slot; // points to whichever slot contains this message
|
||||
uint32_t tx_timestamp;
|
||||
uint32_t rx_timestamp;
|
||||
|
||||
} RX_MESSAGE_INFO_T;
|
||||
|
||||
typedef struct {
|
||||
MESSAGE_EVENT_TYPE_T type;
|
||||
|
||||
struct {
|
||||
// for messages
|
||||
void *addr; // address of message
|
||||
uint16_t slot_delta; // whether this message indicated slot delta
|
||||
uint32_t len; // length of message
|
||||
RX_MSG_SLOTINFO_T *slot; // slot this message is in
|
||||
int32_t service; // service id this message is destined for
|
||||
uint32_t tx_timestamp; // timestamp from the header
|
||||
uint32_t rx_timestamp; // timestamp when we parsed it
|
||||
} message;
|
||||
|
||||
// FIXME: cleanup slot reporting...
|
||||
RX_MSG_SLOTINFO_T *rx_msg;
|
||||
RX_BULK_SLOTINFO_T *rx_bulk;
|
||||
void *tx_handle;
|
||||
MESSAGE_TX_CHANNEL_T tx_channel;
|
||||
|
||||
} MESSAGE_EVENT_T;
|
||||
|
||||
|
||||
// callbacks
|
||||
typedef void VCHI_MESSAGE_DRIVER_EVENT_CALLBACK_T( void *state );
|
||||
|
||||
typedef struct {
|
||||
VCHI_MESSAGE_DRIVER_EVENT_CALLBACK_T *event_callback;
|
||||
} VCHI_MESSAGE_DRIVER_OPEN_T;
|
||||
|
||||
|
||||
// handle to this instance of message driver (as returned by ->open)
|
||||
typedef struct opaque_mhandle_t *VCHI_MDRIVER_HANDLE_T;
|
||||
|
||||
struct opaque_vchi_message_driver_t {
|
||||
VCHI_MDRIVER_HANDLE_T *(*open)( VCHI_MESSAGE_DRIVER_OPEN_T *params, void *state );
|
||||
int32_t (*suspending)( VCHI_MDRIVER_HANDLE_T *handle );
|
||||
int32_t (*resumed)( VCHI_MDRIVER_HANDLE_T *handle );
|
||||
int32_t (*power_control)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T, int32_t enable );
|
||||
int32_t (*add_msg_rx_slot)( VCHI_MDRIVER_HANDLE_T *handle, RX_MSG_SLOTINFO_T *slot ); // rx message
|
||||
int32_t (*add_bulk_rx)( VCHI_MDRIVER_HANDLE_T *handle, void *data, uint32_t len, RX_BULK_SLOTINFO_T *slot ); // rx data (bulk)
|
||||
int32_t (*send)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel, const void *data, uint32_t len, VCHI_MSG_FLAGS_T flags, void *send_handle ); // tx (message & bulk)
|
||||
void (*next_event)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_EVENT_T *event ); // get the next event from message_driver
|
||||
int32_t (*enable)( VCHI_MDRIVER_HANDLE_T *handle );
|
||||
int32_t (*form_message)( VCHI_MDRIVER_HANDLE_T *handle, int32_t service_id, VCHI_MSG_VECTOR_T *vector, uint32_t count, void
|
||||
*address, uint32_t length_avail, uint32_t max_total_length, int32_t pad_to_fill, int32_t allow_partial );
|
||||
|
||||
int32_t (*update_message)( VCHI_MDRIVER_HANDLE_T *handle, void *dest, int16_t *slot_count );
|
||||
int32_t (*buffer_aligned)( VCHI_MDRIVER_HANDLE_T *handle, int tx, int uncached, const void *address, const uint32_t length );
|
||||
void * (*allocate_buffer)( VCHI_MDRIVER_HANDLE_T *handle, uint32_t *length );
|
||||
void (*free_buffer)( VCHI_MDRIVER_HANDLE_T *handle, void *address );
|
||||
int (*rx_slot_size)( VCHI_MDRIVER_HANDLE_T *handle, int msg_size );
|
||||
int (*tx_slot_size)( VCHI_MDRIVER_HANDLE_T *handle, int msg_size );
|
||||
|
||||
int32_t (*tx_supports_terminate)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel );
|
||||
uint32_t (*tx_bulk_chunk_size)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel );
|
||||
int (*tx_alignment)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel );
|
||||
int (*rx_alignment)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_RX_CHANNEL_T channel );
|
||||
void (*form_bulk_aux)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel, const void *data, uint32_t len, uint32_t chunk_size, const void **aux_data, int32_t *aux_len );
|
||||
void (*debug)( VCHI_MDRIVER_HANDLE_T *handle );
|
||||
};
|
||||
|
||||
|
||||
#endif // _VCHI_MESSAGE_H_
|
||||
|
||||
/****************************** End of file ***********************************/
|
373
sys/contrib/vchiq/interface/vchi/vchi.h
Normal file
373
sys/contrib/vchiq/interface/vchi/vchi.h
Normal file
@ -0,0 +1,373 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef VCHI_H_
|
||||
#define VCHI_H_
|
||||
|
||||
#include "interface/vchi/vchi_cfg.h"
|
||||
#include "interface/vchi/vchi_common.h"
|
||||
#include "interface/vchi/connections/connection.h"
|
||||
#include "vchi_mh.h"
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Global defs
|
||||
*****************************************************************************/
|
||||
|
||||
#define VCHI_BULK_ROUND_UP(x) ((((unsigned long)(x))+VCHI_BULK_ALIGN-1) & ~(VCHI_BULK_ALIGN-1))
|
||||
#define VCHI_BULK_ROUND_DOWN(x) (((unsigned long)(x)) & ~(VCHI_BULK_ALIGN-1))
|
||||
#define VCHI_BULK_ALIGN_NBYTES(x) (VCHI_BULK_ALIGNED(x) ? 0 : (VCHI_BULK_ALIGN - ((unsigned long)(x) & (VCHI_BULK_ALIGN-1))))
|
||||
|
||||
#ifdef USE_VCHIQ_ARM
|
||||
#define VCHI_BULK_ALIGNED(x) 1
|
||||
#else
|
||||
#define VCHI_BULK_ALIGNED(x) (((unsigned long)(x) & (VCHI_BULK_ALIGN-1)) == 0)
|
||||
#endif
|
||||
|
||||
struct vchi_version {
|
||||
uint32_t version;
|
||||
uint32_t version_min;
|
||||
};
|
||||
#define VCHI_VERSION(v_) { v_, v_ }
|
||||
#define VCHI_VERSION_EX(v_, m_) { v_, m_ }
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VCHI_VEC_POINTER,
|
||||
VCHI_VEC_HANDLE,
|
||||
VCHI_VEC_LIST
|
||||
} VCHI_MSG_VECTOR_TYPE_T;
|
||||
|
||||
typedef struct vchi_msg_vector_ex {
|
||||
|
||||
VCHI_MSG_VECTOR_TYPE_T type;
|
||||
union
|
||||
{
|
||||
// a memory handle
|
||||
struct
|
||||
{
|
||||
VCHI_MEM_HANDLE_T handle;
|
||||
uint32_t offset;
|
||||
int32_t vec_len;
|
||||
} handle;
|
||||
|
||||
// an ordinary data pointer
|
||||
struct
|
||||
{
|
||||
const void *vec_base;
|
||||
int32_t vec_len;
|
||||
} ptr;
|
||||
|
||||
// a nested vector list
|
||||
struct
|
||||
{
|
||||
struct vchi_msg_vector_ex *vec;
|
||||
uint32_t vec_len;
|
||||
} list;
|
||||
} u;
|
||||
} VCHI_MSG_VECTOR_EX_T;
|
||||
|
||||
|
||||
// Construct an entry in a msg vector for a pointer (p) of length (l)
|
||||
#define VCHI_VEC_POINTER(p,l) VCHI_VEC_POINTER, { { (VCHI_MEM_HANDLE_T)(p), (l) } }
|
||||
|
||||
// Construct an entry in a msg vector for a message handle (h), starting at offset (o) of length (l)
|
||||
#define VCHI_VEC_HANDLE(h,o,l) VCHI_VEC_HANDLE, { { (h), (o), (l) } }
|
||||
|
||||
// Macros to manipulate 'FOURCC' values
|
||||
#define MAKE_FOURCC(x) ((int32_t)( (x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3] ))
|
||||
#define FOURCC_TO_CHAR(x) (x >> 24) & 0xFF,(x >> 16) & 0xFF,(x >> 8) & 0xFF, x & 0xFF
|
||||
|
||||
|
||||
// Opaque service information
|
||||
struct opaque_vchi_service_t;
|
||||
|
||||
// Descriptor for a held message. Allocated by client, initialised by vchi_msg_hold,
|
||||
// vchi_msg_iter_hold or vchi_msg_iter_hold_next. Fields are for internal VCHI use only.
|
||||
typedef struct
|
||||
{
|
||||
struct opaque_vchi_service_t *service;
|
||||
void *message;
|
||||
} VCHI_HELD_MSG_T;
|
||||
|
||||
|
||||
|
||||
// structure used to provide the information needed to open a server or a client
|
||||
typedef struct {
|
||||
struct vchi_version version;
|
||||
int32_t service_id;
|
||||
VCHI_CONNECTION_T *connection;
|
||||
uint32_t rx_fifo_size;
|
||||
uint32_t tx_fifo_size;
|
||||
VCHI_CALLBACK_T callback;
|
||||
void *callback_param;
|
||||
/* client intends to receive bulk transfers of
|
||||
odd lengths or into unaligned buffers */
|
||||
int32_t want_unaligned_bulk_rx;
|
||||
/* client intends to transmit bulk transfers of
|
||||
odd lengths or out of unaligned buffers */
|
||||
int32_t want_unaligned_bulk_tx;
|
||||
/* client wants to check CRCs on (bulk) xfers.
|
||||
Only needs to be set at 1 end - will do both directions. */
|
||||
int32_t want_crc;
|
||||
} SERVICE_CREATION_T;
|
||||
|
||||
// Opaque handle for a VCHI instance
|
||||
typedef struct opaque_vchi_instance_handle_t *VCHI_INSTANCE_T;
|
||||
|
||||
// Opaque handle for a server or client
|
||||
typedef struct opaque_vchi_service_handle_t *VCHI_SERVICE_HANDLE_T;
|
||||
|
||||
// Service registration & startup
|
||||
typedef void (*VCHI_SERVICE_INIT)(VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections);
|
||||
|
||||
typedef struct service_info_tag {
|
||||
const char * const vll_filename; /* VLL to load to start this service. This is an empty string if VLL is "static" */
|
||||
VCHI_SERVICE_INIT init; /* Service initialisation function */
|
||||
void *vll_handle; /* VLL handle; NULL when unloaded or a "static VLL" in build */
|
||||
} SERVICE_INFO_T;
|
||||
|
||||
/******************************************************************************
|
||||
Global funcs - implementation is specific to which side you are on (local / remote)
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern /*@observer@*/ VCHI_CONNECTION_T * vchi_create_connection( const VCHI_CONNECTION_API_T * function_table,
|
||||
const VCHI_MESSAGE_DRIVER_T * low_level);
|
||||
|
||||
|
||||
// Routine used to initialise the vchi on both local + remote connections
|
||||
extern int32_t vchi_initialise( VCHI_INSTANCE_T *instance_handle );
|
||||
|
||||
extern int32_t vchi_exit( void );
|
||||
|
||||
extern int32_t vchi_connect( VCHI_CONNECTION_T **connections,
|
||||
const uint32_t num_connections,
|
||||
VCHI_INSTANCE_T instance_handle );
|
||||
|
||||
//When this is called, ensure that all services have no data pending.
|
||||
//Bulk transfers can remain 'queued'
|
||||
extern int32_t vchi_disconnect( VCHI_INSTANCE_T instance_handle );
|
||||
|
||||
// Global control over bulk CRC checking
|
||||
extern int32_t vchi_crc_control( VCHI_CONNECTION_T *connection,
|
||||
VCHI_CRC_CONTROL_T control );
|
||||
|
||||
// helper functions
|
||||
extern void * vchi_allocate_buffer(VCHI_SERVICE_HANDLE_T handle, uint32_t *length);
|
||||
extern void vchi_free_buffer(VCHI_SERVICE_HANDLE_T handle, void *address);
|
||||
extern uint32_t vchi_current_time(VCHI_INSTANCE_T instance_handle);
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Global service API
|
||||
*****************************************************************************/
|
||||
// Routine to create a named service
|
||||
extern int32_t vchi_service_create( VCHI_INSTANCE_T instance_handle,
|
||||
SERVICE_CREATION_T *setup,
|
||||
VCHI_SERVICE_HANDLE_T *handle );
|
||||
|
||||
// Routine to destory a service
|
||||
extern int32_t vchi_service_destroy( const VCHI_SERVICE_HANDLE_T handle );
|
||||
|
||||
// Routine to open a named service
|
||||
extern int32_t vchi_service_open( VCHI_INSTANCE_T instance_handle,
|
||||
SERVICE_CREATION_T *setup,
|
||||
VCHI_SERVICE_HANDLE_T *handle);
|
||||
|
||||
extern int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle,
|
||||
short *peer_version );
|
||||
|
||||
// Routine to close a named service
|
||||
extern int32_t vchi_service_close( const VCHI_SERVICE_HANDLE_T handle );
|
||||
|
||||
// Routine to increment ref count on a named service
|
||||
extern int32_t vchi_service_use( const VCHI_SERVICE_HANDLE_T handle );
|
||||
|
||||
// Routine to decrement ref count on a named service
|
||||
extern int32_t vchi_service_release( const VCHI_SERVICE_HANDLE_T handle );
|
||||
|
||||
// Routine to send a message accross a service
|
||||
extern int32_t vchi_msg_queue( VCHI_SERVICE_HANDLE_T handle,
|
||||
const void *data,
|
||||
uint32_t data_size,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *msg_handle );
|
||||
|
||||
// scatter-gather (vector) and send message
|
||||
int32_t vchi_msg_queuev_ex( VCHI_SERVICE_HANDLE_T handle,
|
||||
VCHI_MSG_VECTOR_EX_T *vector,
|
||||
uint32_t count,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *msg_handle );
|
||||
|
||||
// legacy scatter-gather (vector) and send message, only handles pointers
|
||||
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 );
|
||||
|
||||
// Routine to receive a msg from a service
|
||||
// Dequeue is equivalent to hold, copy into client buffer, release
|
||||
extern 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 );
|
||||
|
||||
// Routine to look at a message in place.
|
||||
// The message is not dequeued, so a subsequent call to peek or dequeue
|
||||
// will return the same message.
|
||||
extern int32_t vchi_msg_peek( VCHI_SERVICE_HANDLE_T handle,
|
||||
void **data,
|
||||
uint32_t *msg_size,
|
||||
VCHI_FLAGS_T flags );
|
||||
|
||||
// Routine to remove a message after it has been read in place with peek
|
||||
// The first message on the queue is dequeued.
|
||||
extern int32_t vchi_msg_remove( VCHI_SERVICE_HANDLE_T handle );
|
||||
|
||||
// Routine to look at a message in place.
|
||||
// The message is dequeued, so the caller is left holding it; the descriptor is
|
||||
// filled in and must be released when the user has finished with the message.
|
||||
extern int32_t vchi_msg_hold( VCHI_SERVICE_HANDLE_T handle,
|
||||
void **data, // } may be NULL, as info can be
|
||||
uint32_t *msg_size, // } obtained from HELD_MSG_T
|
||||
VCHI_FLAGS_T flags,
|
||||
VCHI_HELD_MSG_T *message_descriptor );
|
||||
|
||||
// Initialise an iterator to look through messages in place
|
||||
extern int32_t vchi_msg_look_ahead( VCHI_SERVICE_HANDLE_T handle,
|
||||
VCHI_MSG_ITER_T *iter,
|
||||
VCHI_FLAGS_T flags );
|
||||
|
||||
/******************************************************************************
|
||||
Global service support API - operations on held messages and message iterators
|
||||
*****************************************************************************/
|
||||
|
||||
// Routine to get the address of a held message
|
||||
extern void *vchi_held_msg_ptr( const VCHI_HELD_MSG_T *message );
|
||||
|
||||
// Routine to get the size of a held message
|
||||
extern int32_t vchi_held_msg_size( const VCHI_HELD_MSG_T *message );
|
||||
|
||||
// Routine to get the transmit timestamp as written into the header by the peer
|
||||
extern uint32_t vchi_held_msg_tx_timestamp( const VCHI_HELD_MSG_T *message );
|
||||
|
||||
// Routine to get the reception timestamp, written as we parsed the header
|
||||
extern uint32_t vchi_held_msg_rx_timestamp( const VCHI_HELD_MSG_T *message );
|
||||
|
||||
// Routine to release a held message after it has been processed
|
||||
extern int32_t vchi_held_msg_release( VCHI_HELD_MSG_T *message );
|
||||
|
||||
// Indicates whether the iterator has a next message.
|
||||
extern int32_t vchi_msg_iter_has_next( const VCHI_MSG_ITER_T *iter );
|
||||
|
||||
// Return the pointer and length for the next message and advance the iterator.
|
||||
extern int32_t vchi_msg_iter_next( VCHI_MSG_ITER_T *iter,
|
||||
void **data,
|
||||
uint32_t *msg_size );
|
||||
|
||||
// Remove the last message returned by vchi_msg_iter_next.
|
||||
// Can only be called once after each call to vchi_msg_iter_next.
|
||||
extern int32_t vchi_msg_iter_remove( VCHI_MSG_ITER_T *iter );
|
||||
|
||||
// Hold the last message returned by vchi_msg_iter_next.
|
||||
// Can only be called once after each call to vchi_msg_iter_next.
|
||||
extern int32_t vchi_msg_iter_hold( VCHI_MSG_ITER_T *iter,
|
||||
VCHI_HELD_MSG_T *message );
|
||||
|
||||
// Return information for the next message, and hold it, advancing the iterator.
|
||||
extern int32_t vchi_msg_iter_hold_next( VCHI_MSG_ITER_T *iter,
|
||||
void **data, // } may be NULL
|
||||
uint32_t *msg_size, // }
|
||||
VCHI_HELD_MSG_T *message );
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Global bulk API
|
||||
*****************************************************************************/
|
||||
|
||||
// Routine to prepare interface for a transfer from the other side
|
||||
extern int32_t vchi_bulk_queue_receive( VCHI_SERVICE_HANDLE_T handle,
|
||||
void *data_dst,
|
||||
uint32_t data_size,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *transfer_handle );
|
||||
|
||||
|
||||
// Prepare interface for a transfer from the other side into relocatable memory.
|
||||
int32_t vchi_bulk_queue_receive_reloc( const VCHI_SERVICE_HANDLE_T handle,
|
||||
VCHI_MEM_HANDLE_T h_dst,
|
||||
uint32_t offset,
|
||||
uint32_t data_size,
|
||||
const VCHI_FLAGS_T flags,
|
||||
void * const bulk_handle );
|
||||
|
||||
// Routine to queue up data ready for transfer to the other (once they have signalled they are ready)
|
||||
extern int32_t vchi_bulk_queue_transmit( VCHI_SERVICE_HANDLE_T handle,
|
||||
void *data_src,
|
||||
uint32_t data_size,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *transfer_handle );
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Configuration plumbing
|
||||
*****************************************************************************/
|
||||
|
||||
// function prototypes for the different mid layers (the state info gives the different physical connections)
|
||||
extern const VCHI_CONNECTION_API_T *single_get_func_table( void );
|
||||
//extern const VCHI_CONNECTION_API_T *local_server_get_func_table( void );
|
||||
//extern const VCHI_CONNECTION_API_T *local_client_get_func_table( void );
|
||||
|
||||
// declare all message drivers here
|
||||
const VCHI_MESSAGE_DRIVER_T *vchi_mphi_message_driver_func_table( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
extern 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 *transfer_handle );
|
||||
#endif /* VCHI_H_ */
|
||||
|
||||
/****************************** End of file **********************************/
|
224
sys/contrib/vchiq/interface/vchi/vchi_cfg.h
Normal file
224
sys/contrib/vchiq/interface/vchi/vchi_cfg.h
Normal file
@ -0,0 +1,224 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef VCHI_CFG_H_
|
||||
#define VCHI_CFG_H_
|
||||
|
||||
/****************************************************************************************
|
||||
* Defines in this first section are part of the VCHI API and may be examined by VCHI
|
||||
* services.
|
||||
***************************************************************************************/
|
||||
|
||||
/* Required alignment of base addresses for bulk transfer, if unaligned transfers are not enabled */
|
||||
/* Really determined by the message driver, and should be available from a run-time call. */
|
||||
#ifndef VCHI_BULK_ALIGN
|
||||
# if __VCCOREVER__ >= 0x04000000
|
||||
# define VCHI_BULK_ALIGN 32 // Allows for the need to do cache cleans
|
||||
# else
|
||||
# define VCHI_BULK_ALIGN 16
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Required length multiple for bulk transfers, if unaligned transfers are not enabled */
|
||||
/* May be less than or greater than VCHI_BULK_ALIGN */
|
||||
/* Really determined by the message driver, and should be available from a run-time call. */
|
||||
#ifndef VCHI_BULK_GRANULARITY
|
||||
# if __VCCOREVER__ >= 0x04000000
|
||||
# define VCHI_BULK_GRANULARITY 32 // Allows for the need to do cache cleans
|
||||
# else
|
||||
# define VCHI_BULK_GRANULARITY 16
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The largest possible message to be queued with vchi_msg_queue. */
|
||||
#ifndef VCHI_MAX_MSG_SIZE
|
||||
# if defined VCHI_LOCAL_HOST_PORT
|
||||
# define VCHI_MAX_MSG_SIZE 16384 // makes file transfers fast, but should they be using bulk?
|
||||
# else
|
||||
# define VCHI_MAX_MSG_SIZE 4096 // NOTE: THIS MUST BE LARGER THAN OR EQUAL TO THE SIZE OF THE KHRONOS MERGE BUFFER!!
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/******************************************************************************************
|
||||
* Defines below are system configuration options, and should not be used by VCHI services.
|
||||
*****************************************************************************************/
|
||||
|
||||
/* How many connections can we support? A localhost implementation uses 2 connections,
|
||||
* 1 for host-app, 1 for VMCS, and these are hooked together by a loopback MPHI VCFW
|
||||
* driver. */
|
||||
#ifndef VCHI_MAX_NUM_CONNECTIONS
|
||||
# define VCHI_MAX_NUM_CONNECTIONS 3
|
||||
#endif
|
||||
|
||||
/* How many services can we open per connection? Extending this doesn't cost processing time, just a small
|
||||
* amount of static memory. */
|
||||
#ifndef VCHI_MAX_SERVICES_PER_CONNECTION
|
||||
# define VCHI_MAX_SERVICES_PER_CONNECTION 36
|
||||
#endif
|
||||
|
||||
/* Adjust if using a message driver that supports more logical TX channels */
|
||||
#ifndef VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION
|
||||
# define VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION 9 // 1 MPHI + 8 CCP2 logical channels
|
||||
#endif
|
||||
|
||||
/* Adjust if using a message driver that supports more logical RX channels */
|
||||
#ifndef VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION
|
||||
# define VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION 1 // 1 MPHI
|
||||
#endif
|
||||
|
||||
/* How many receive slots do we use. This times VCHI_MAX_MSG_SIZE gives the effective
|
||||
* receive queue space, less message headers. */
|
||||
#ifndef VCHI_NUM_READ_SLOTS
|
||||
# if defined(VCHI_LOCAL_HOST_PORT)
|
||||
# define VCHI_NUM_READ_SLOTS 4
|
||||
# else
|
||||
# define VCHI_NUM_READ_SLOTS 48
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Do we utilise overrun facility for receive message slots? Can aid peer transmit
|
||||
* performance. Only define on VideoCore end, talking to host.
|
||||
*/
|
||||
//#define VCHI_MSG_RX_OVERRUN
|
||||
|
||||
/* How many transmit slots do we use. Generally don't need many, as the hardware driver
|
||||
* underneath VCHI will usually have its own buffering. */
|
||||
#ifndef VCHI_NUM_WRITE_SLOTS
|
||||
# define VCHI_NUM_WRITE_SLOTS 4
|
||||
#endif
|
||||
|
||||
/* If a service has held or queued received messages in VCHI_XOFF_THRESHOLD or more slots,
|
||||
* then it's taking up too much buffer space, and the peer service will be told to stop
|
||||
* transmitting with an XOFF message. For this to be effective, the VCHI_NUM_READ_SLOTS
|
||||
* needs to be considerably bigger than VCHI_NUM_WRITE_SLOTS, or the transmit latency
|
||||
* is too high. */
|
||||
#ifndef VCHI_XOFF_THRESHOLD
|
||||
# define VCHI_XOFF_THRESHOLD (VCHI_NUM_READ_SLOTS / 2)
|
||||
#endif
|
||||
|
||||
/* After we've sent an XOFF, the peer will be told to resume transmission once the local
|
||||
* service has dequeued/released enough messages that it's now occupying
|
||||
* VCHI_XON_THRESHOLD slots or fewer. */
|
||||
#ifndef VCHI_XON_THRESHOLD
|
||||
# define VCHI_XON_THRESHOLD (VCHI_NUM_READ_SLOTS / 4)
|
||||
#endif
|
||||
|
||||
/* A size below which a bulk transfer omits the handshake completely and always goes
|
||||
* via the message channel, if bulk auxiliary is being sent on that service. (The user
|
||||
* can guarantee this by enabling unaligned transmits).
|
||||
* Not API. */
|
||||
#ifndef VCHI_MIN_BULK_SIZE
|
||||
# define VCHI_MIN_BULK_SIZE ( VCHI_MAX_MSG_SIZE / 2 < 4096 ? VCHI_MAX_MSG_SIZE / 2 : 4096 )
|
||||
#endif
|
||||
|
||||
/* Maximum size of bulk transmission chunks, for each interface type. A trade-off between
|
||||
* speed and latency; the smaller the chunk size the better change of messages and other
|
||||
* bulk transmissions getting in when big bulk transfers are happening. Set to 0 to not
|
||||
* break transmissions into chunks.
|
||||
*/
|
||||
#ifndef VCHI_MAX_BULK_CHUNK_SIZE_MPHI
|
||||
# define VCHI_MAX_BULK_CHUNK_SIZE_MPHI (16 * 1024)
|
||||
#endif
|
||||
|
||||
/* NB Chunked CCP2 transmissions violate the letter of the CCP2 spec by using "JPEG8" mode
|
||||
* with multiple-line frames. Only use if the receiver can cope. */
|
||||
#ifndef VCHI_MAX_BULK_CHUNK_SIZE_CCP2
|
||||
# define VCHI_MAX_BULK_CHUNK_SIZE_CCP2 0
|
||||
#endif
|
||||
|
||||
/* How many TX messages can we have pending in our transmit slots. Once exhausted,
|
||||
* vchi_msg_queue will be blocked. */
|
||||
#ifndef VCHI_TX_MSG_QUEUE_SIZE
|
||||
# define VCHI_TX_MSG_QUEUE_SIZE 256
|
||||
#endif
|
||||
|
||||
/* How many RX messages can we have parsed in the receive slots. Once exhausted, parsing
|
||||
* will be suspended until older messages are dequeued/released. */
|
||||
#ifndef VCHI_RX_MSG_QUEUE_SIZE
|
||||
# define VCHI_RX_MSG_QUEUE_SIZE 256
|
||||
#endif
|
||||
|
||||
/* Really should be able to cope if we run out of received message descriptors, by
|
||||
* suspending parsing as the comment above says, but we don't. This sweeps the issue
|
||||
* under the carpet. */
|
||||
#if VCHI_RX_MSG_QUEUE_SIZE < (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS
|
||||
# undef VCHI_RX_MSG_QUEUE_SIZE
|
||||
# define VCHI_RX_MSG_QUEUE_SIZE (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS
|
||||
#endif
|
||||
|
||||
/* How many bulk transmits can we have pending. Once exhausted, vchi_bulk_queue_transmit
|
||||
* will be blocked. */
|
||||
#ifndef VCHI_TX_BULK_QUEUE_SIZE
|
||||
# define VCHI_TX_BULK_QUEUE_SIZE 64
|
||||
#endif
|
||||
|
||||
/* How many bulk receives can we have pending. Once exhausted, vchi_bulk_queue_receive
|
||||
* will be blocked. */
|
||||
#ifndef VCHI_RX_BULK_QUEUE_SIZE
|
||||
# define VCHI_RX_BULK_QUEUE_SIZE 64
|
||||
#endif
|
||||
|
||||
/* A limit on how many outstanding bulk requests we expect the peer to give us. If
|
||||
* the peer asks for more than this, VCHI will fail and assert. The number is determined
|
||||
* by the peer's hardware - it's the number of outstanding requests that can be queued
|
||||
* on all bulk channels. VC3's MPHI peripheral allows 16. */
|
||||
#ifndef VCHI_MAX_PEER_BULK_REQUESTS
|
||||
# define VCHI_MAX_PEER_BULK_REQUESTS 32
|
||||
#endif
|
||||
|
||||
/* Define VCHI_CCP2TX_MANUAL_POWER if the host tells us when to turn the CCP2
|
||||
* transmitter on and off.
|
||||
*/
|
||||
/*#define VCHI_CCP2TX_MANUAL_POWER*/
|
||||
|
||||
#ifndef VCHI_CCP2TX_MANUAL_POWER
|
||||
|
||||
/* Timeout (in milliseconds) for putting the CCP2TX interface into IDLE state. Set
|
||||
* negative for no IDLE.
|
||||
*/
|
||||
# ifndef VCHI_CCP2TX_IDLE_TIMEOUT
|
||||
# define VCHI_CCP2TX_IDLE_TIMEOUT 5
|
||||
# endif
|
||||
|
||||
/* Timeout (in milliseconds) for putting the CCP2TX interface into OFF state. Set
|
||||
* negative for no OFF.
|
||||
*/
|
||||
# ifndef VCHI_CCP2TX_OFF_TIMEOUT
|
||||
# define VCHI_CCP2TX_OFF_TIMEOUT 1000
|
||||
# endif
|
||||
|
||||
#endif /* VCHI_CCP2TX_MANUAL_POWER */
|
||||
|
||||
#endif /* VCHI_CFG_H_ */
|
||||
|
||||
/****************************** End of file **********************************/
|
71
sys/contrib/vchiq/interface/vchi/vchi_cfg_internal.h
Normal file
71
sys/contrib/vchiq/interface/vchi/vchi_cfg_internal.h
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef VCHI_CFG_INTERNAL_H_
|
||||
#define VCHI_CFG_INTERNAL_H_
|
||||
|
||||
/****************************************************************************************
|
||||
* Control optimisation attempts.
|
||||
***************************************************************************************/
|
||||
|
||||
// Don't use lots of short-term locks - use great long ones, reducing the overall locks-per-second
|
||||
#define VCHI_COARSE_LOCKING
|
||||
|
||||
// Avoid lock then unlock on exit from blocking queue operations (msg tx, bulk rx/tx)
|
||||
// (only relevant if VCHI_COARSE_LOCKING)
|
||||
#define VCHI_ELIDE_BLOCK_EXIT_LOCK
|
||||
|
||||
// Avoid lock on non-blocking peek
|
||||
// (only relevant if VCHI_COARSE_LOCKING)
|
||||
#define VCHI_AVOID_PEEK_LOCK
|
||||
|
||||
// Use one slot-handler thread per connection, rather than 1 thread dealing with all connections in rotation.
|
||||
#define VCHI_MULTIPLE_HANDLER_THREADS
|
||||
|
||||
// Put free descriptors onto the head of the free queue, rather than the tail, so that we don't thrash
|
||||
// our way through the pool of descriptors.
|
||||
#define VCHI_PUSH_FREE_DESCRIPTORS_ONTO_HEAD
|
||||
|
||||
// Don't issue a MSG_AVAILABLE callback for every single message. Possibly only safe if VCHI_COARSE_LOCKING.
|
||||
#define VCHI_FEWER_MSG_AVAILABLE_CALLBACKS
|
||||
|
||||
// Don't use message descriptors for TX messages that don't need them
|
||||
#define VCHI_MINIMISE_TX_MSG_DESCRIPTORS
|
||||
|
||||
// Nano-locks for multiqueue
|
||||
//#define VCHI_MQUEUE_NANOLOCKS
|
||||
|
||||
// Lock-free(er) dequeuing
|
||||
//#define VCHI_RX_NANOLOCKS
|
||||
|
||||
#endif /*VCHI_CFG_INTERNAL_H_*/
|
163
sys/contrib/vchiq/interface/vchi/vchi_common.h
Normal file
163
sys/contrib/vchiq/interface/vchi/vchi_common.h
Normal file
@ -0,0 +1,163 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef VCHI_COMMON_H_
|
||||
#define VCHI_COMMON_H_
|
||||
|
||||
|
||||
//flags used when sending messages (must be bitmapped)
|
||||
typedef enum
|
||||
{
|
||||
VCHI_FLAGS_NONE = 0x0,
|
||||
VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE = 0x1, // waits for message to be received, or sent (NB. not the same as being seen on other side)
|
||||
VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE = 0x2, // run a callback when message sent
|
||||
VCHI_FLAGS_BLOCK_UNTIL_QUEUED = 0x4, // return once the transfer is in a queue ready to go
|
||||
VCHI_FLAGS_ALLOW_PARTIAL = 0x8,
|
||||
VCHI_FLAGS_BLOCK_UNTIL_DATA_READ = 0x10,
|
||||
VCHI_FLAGS_CALLBACK_WHEN_DATA_READ = 0x20,
|
||||
|
||||
VCHI_FLAGS_ALIGN_SLOT = 0x000080, // internal use only
|
||||
VCHI_FLAGS_BULK_AUX_QUEUED = 0x010000, // internal use only
|
||||
VCHI_FLAGS_BULK_AUX_COMPLETE = 0x020000, // internal use only
|
||||
VCHI_FLAGS_BULK_DATA_QUEUED = 0x040000, // internal use only
|
||||
VCHI_FLAGS_BULK_DATA_COMPLETE = 0x080000, // internal use only
|
||||
VCHI_FLAGS_INTERNAL = 0xFF0000
|
||||
} VCHI_FLAGS_T;
|
||||
|
||||
// constants for vchi_crc_control()
|
||||
typedef enum {
|
||||
VCHI_CRC_NOTHING = -1,
|
||||
VCHI_CRC_PER_SERVICE = 0,
|
||||
VCHI_CRC_EVERYTHING = 1,
|
||||
} VCHI_CRC_CONTROL_T;
|
||||
|
||||
//callback reasons when an event occurs on a service
|
||||
typedef enum
|
||||
{
|
||||
VCHI_CALLBACK_REASON_MIN,
|
||||
|
||||
//This indicates that there is data available
|
||||
//handle is the msg id that was transmitted with the data
|
||||
// When a message is received and there was no FULL message available previously, send callback
|
||||
// Tasks get kicked by the callback, reset their event and try and read from the fifo until it fails
|
||||
VCHI_CALLBACK_MSG_AVAILABLE,
|
||||
VCHI_CALLBACK_MSG_SENT,
|
||||
VCHI_CALLBACK_MSG_SPACE_AVAILABLE, // XXX not yet implemented
|
||||
|
||||
// This indicates that a transfer from the other side has completed
|
||||
VCHI_CALLBACK_BULK_RECEIVED,
|
||||
//This indicates that data queued up to be sent has now gone
|
||||
//handle is the msg id that was used when sending the data
|
||||
VCHI_CALLBACK_BULK_SENT,
|
||||
VCHI_CALLBACK_BULK_RX_SPACE_AVAILABLE, // XXX not yet implemented
|
||||
VCHI_CALLBACK_BULK_TX_SPACE_AVAILABLE, // XXX not yet implemented
|
||||
|
||||
VCHI_CALLBACK_SERVICE_CLOSED,
|
||||
|
||||
// this side has sent XOFF to peer due to lack of data consumption by service
|
||||
// (suggests the service may need to take some recovery action if it has
|
||||
// been deliberately holding off consuming data)
|
||||
VCHI_CALLBACK_SENT_XOFF,
|
||||
VCHI_CALLBACK_SENT_XON,
|
||||
|
||||
// indicates that a bulk transfer has finished reading the source buffer
|
||||
VCHI_CALLBACK_BULK_DATA_READ,
|
||||
|
||||
// power notification events (currently host side only)
|
||||
VCHI_CALLBACK_PEER_OFF,
|
||||
VCHI_CALLBACK_PEER_SUSPENDED,
|
||||
VCHI_CALLBACK_PEER_ON,
|
||||
VCHI_CALLBACK_PEER_RESUMED,
|
||||
VCHI_CALLBACK_FORCED_POWER_OFF,
|
||||
|
||||
#ifdef USE_VCHIQ_ARM
|
||||
// some extra notifications provided by vchiq_arm
|
||||
VCHI_CALLBACK_SERVICE_OPENED,
|
||||
VCHI_CALLBACK_BULK_RECEIVE_ABORTED,
|
||||
VCHI_CALLBACK_BULK_TRANSMIT_ABORTED,
|
||||
#endif
|
||||
|
||||
VCHI_CALLBACK_REASON_MAX
|
||||
} VCHI_CALLBACK_REASON_T;
|
||||
|
||||
//Calback used by all services / bulk transfers
|
||||
typedef void (*VCHI_CALLBACK_T)( void *callback_param, //my service local param
|
||||
VCHI_CALLBACK_REASON_T reason,
|
||||
void *handle ); //for transmitting msg's only
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Define vector struct for scatter-gather (vector) operations
|
||||
* Vectors can be nested - if a vector element has negative length, then
|
||||
* the data pointer is treated as pointing to another vector array, with
|
||||
* '-vec_len' elements. Thus to append a header onto an existing vector,
|
||||
* you can do this:
|
||||
*
|
||||
* void foo(const VCHI_MSG_VECTOR_T *v, int n)
|
||||
* {
|
||||
* VCHI_MSG_VECTOR_T nv[2];
|
||||
* nv[0].vec_base = my_header;
|
||||
* nv[0].vec_len = sizeof my_header;
|
||||
* nv[1].vec_base = v;
|
||||
* nv[1].vec_len = -n;
|
||||
* ...
|
||||
*
|
||||
*/
|
||||
typedef struct vchi_msg_vector {
|
||||
const void *vec_base;
|
||||
int32_t vec_len;
|
||||
} VCHI_MSG_VECTOR_T;
|
||||
|
||||
// Opaque type for a connection API
|
||||
typedef struct opaque_vchi_connection_api_t VCHI_CONNECTION_API_T;
|
||||
|
||||
// Opaque type for a message driver
|
||||
typedef struct opaque_vchi_message_driver_t VCHI_MESSAGE_DRIVER_T;
|
||||
|
||||
|
||||
// Iterator structure for reading ahead through received message queue. Allocated by client,
|
||||
// initialised by vchi_msg_look_ahead. Fields are for internal VCHI use only.
|
||||
// Iterates over messages in queue at the instant of the call to vchi_msg_lookahead -
|
||||
// will not proceed to messages received since. Behaviour is undefined if an iterator
|
||||
// is used again after messages for that service are removed/dequeued by any
|
||||
// means other than vchi_msg_iter_... calls on the iterator itself.
|
||||
typedef struct {
|
||||
struct opaque_vchi_service_t *service;
|
||||
void *last;
|
||||
void *next;
|
||||
void *remove;
|
||||
} VCHI_MSG_ITER_T;
|
||||
|
||||
|
||||
#endif // VCHI_COMMON_H_
|
42
sys/contrib/vchiq/interface/vchi/vchi_mh.h
Normal file
42
sys/contrib/vchiq/interface/vchi/vchi_mh.h
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef VCHI_MH_H_
|
||||
#define VCHI_MH_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef int32_t VCHI_MEM_HANDLE_T;
|
||||
#define VCHI_MEM_HANDLE_INVALID 0
|
||||
|
||||
#endif
|
41
sys/contrib/vchiq/interface/vchiq_arm/vchiq.h
Normal file
41
sys/contrib/vchiq/interface/vchiq_arm/vchiq.h
Normal file
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef VCHIQ_VCHIQ_H
|
||||
#define VCHIQ_VCHIQ_H
|
||||
|
||||
#include "vchiq_if.h"
|
||||
#include "vchiq_util.h"
|
||||
|
||||
#endif
|
||||
|
42
sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835.h
Normal file
42
sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835.h
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef 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 */
|
580
sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c
Normal file
580
sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c
Normal file
@ -0,0 +1,580 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <interface/compat/vchi_bsd.h>
|
||||
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/rwlock.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_extern.h>
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <vm/vm_object.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_pager.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_phys.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <arm/broadcom/bcm2835/bcm2835_mbox.h>
|
||||
#include <arm/broadcom/bcm2835/bcm2835_vcbus.h>
|
||||
|
||||
MALLOC_DEFINE(M_VCPAGELIST, "vcpagelist", "VideoCore pagelist memory");
|
||||
|
||||
#define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32)
|
||||
|
||||
#define VCHIQ_DOORBELL_IRQ IRQ_ARM_DOORBELL_0
|
||||
#define VCHIQ_ARM_ADDRESS(x) ((void *)PHYS_TO_VCBUS(pmap_kextract((vm_offset_t)(x))))
|
||||
|
||||
#include "vchiq_arm.h"
|
||||
#include "vchiq_2835.h"
|
||||
#include "vchiq_connected.h"
|
||||
|
||||
#define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2)
|
||||
|
||||
typedef struct vchiq_2835_state_struct {
|
||||
int inited;
|
||||
VCHIQ_ARM_STATE_T arm_state;
|
||||
} VCHIQ_2835_ARM_STATE_T;
|
||||
|
||||
static char *g_slot_mem;
|
||||
static int g_slot_mem_size;
|
||||
vm_paddr_t g_slot_phys;
|
||||
/* BSD DMA */
|
||||
bus_dma_tag_t bcm_slots_dma_tag;
|
||||
bus_dmamap_t bcm_slots_dma_map;
|
||||
|
||||
static FRAGMENTS_T *g_fragments_base;
|
||||
static FRAGMENTS_T *g_free_fragments;
|
||||
struct semaphore g_free_fragments_sema;
|
||||
|
||||
static DEFINE_SEMAPHORE(g_free_fragments_mutex);
|
||||
|
||||
typedef struct bulkinfo_struct {
|
||||
PAGELIST_T *pagelist;
|
||||
bus_dma_tag_t pagelist_dma_tag;
|
||||
bus_dmamap_t pagelist_dma_map;
|
||||
void *buf;
|
||||
size_t size;
|
||||
} BULKINFO_T;
|
||||
|
||||
static int
|
||||
create_pagelist(char __user *buf, size_t count, unsigned short type,
|
||||
struct proc *p, BULKINFO_T *bi);
|
||||
|
||||
static void
|
||||
free_pagelist(BULKINFO_T *bi, int actual);
|
||||
|
||||
static void
|
||||
vchiq_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
|
||||
{
|
||||
bus_addr_t *addr;
|
||||
|
||||
if (err)
|
||||
return;
|
||||
|
||||
addr = (bus_addr_t*)arg;
|
||||
*addr = PHYS_TO_VCBUS(segs[0].ds_addr);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
err = bus_dma_tag_create(
|
||||
NULL,
|
||||
PAGE_SIZE, 0, /* alignment, boundary */
|
||||
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
g_slot_mem_size + frag_mem_size, 1, /* maxsize, nsegments */
|
||||
g_slot_mem_size + frag_mem_size, 0, /* maxsegsize, flags */
|
||||
NULL, NULL, /* lockfunc, lockarg */
|
||||
&bcm_slots_dma_tag);
|
||||
|
||||
err = bus_dmamem_alloc(bcm_slots_dma_tag, (void **)&g_slot_mem,
|
||||
BUS_DMA_COHERENT | BUS_DMA_WAITOK, &bcm_slots_dma_map);
|
||||
if (err) {
|
||||
vchiq_log_error(vchiq_core_log_level, "Unable to allocate channel memory");
|
||||
err = -ENOMEM;
|
||||
goto failed_alloc;
|
||||
}
|
||||
|
||||
err = bus_dmamap_load(bcm_slots_dma_tag, bcm_slots_dma_map, g_slot_mem,
|
||||
g_slot_mem_size + frag_mem_size, vchiq_dmamap_cb,
|
||||
&g_slot_phys, 0);
|
||||
|
||||
if (err) {
|
||||
vchiq_log_error(vchiq_core_log_level, "cannot load DMA map");
|
||||
err = -ENOMEM;
|
||||
goto failed_load;
|
||||
}
|
||||
|
||||
WARN_ON(((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;
|
||||
}
|
||||
|
||||
bcm_mbox_write(BCM2835_MBOX_CHAN_VCHIQ, (unsigned int)g_slot_phys);
|
||||
|
||||
vchiq_log_info(vchiq_arm_log_level,
|
||||
"vchiq_init - done (slots %x, phys %x)",
|
||||
(unsigned int)vchiq_slot_zero, g_slot_phys);
|
||||
|
||||
vchiq_call_connected_callbacks();
|
||||
|
||||
return 0;
|
||||
|
||||
failed_vchiq_init:
|
||||
failed_init_slots:
|
||||
failed_load:
|
||||
bus_dmamap_unload(bcm_slots_dma_tag, bcm_slots_dma_map);
|
||||
failed_alloc:
|
||||
bus_dmamap_destroy(bcm_slots_dma_tag, bcm_slots_dma_map);
|
||||
bus_dma_tag_destroy(bcm_slots_dma_tag);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void __exit
|
||||
vchiq_platform_exit(VCHIQ_STATE_T *state)
|
||||
{
|
||||
|
||||
bus_dmamap_unload(bcm_slots_dma_tag, bcm_slots_dma_map);
|
||||
bus_dmamap_destroy(bcm_slots_dma_tag, bcm_slots_dma_map);
|
||||
bus_dma_tag_destroy(bcm_slots_dma_tag);
|
||||
}
|
||||
|
||||
VCHIQ_STATUS_T
|
||||
vchiq_platform_init_state(VCHIQ_STATE_T *state)
|
||||
{
|
||||
VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
|
||||
state->platform_state = kzalloc(sizeof(VCHIQ_2835_ARM_STATE_T), GFP_KERNEL);
|
||||
((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited = 1;
|
||||
status = vchiq_arm_init_state(state, &((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->arm_state);
|
||||
if(status != VCHIQ_SUCCESS)
|
||||
{
|
||||
((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited = 0;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
VCHIQ_ARM_STATE_T*
|
||||
vchiq_platform_get_arm_state(VCHIQ_STATE_T *state)
|
||||
{
|
||||
if(!((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited)
|
||||
{
|
||||
BUG();
|
||||
}
|
||||
return &((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->arm_state;
|
||||
}
|
||||
|
||||
int
|
||||
vchiq_copy_from_user(void *dst, const void *src, int size)
|
||||
{
|
||||
|
||||
if (((vm_offset_t)(src)) < VM_MIN_KERNEL_ADDRESS) {
|
||||
int error = copyin(src, dst, size);
|
||||
return error ? VCHIQ_ERROR : VCHIQ_SUCCESS;
|
||||
}
|
||||
else
|
||||
bcopy(src, dst, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
BULKINFO_T *bi;
|
||||
int ret;
|
||||
|
||||
WARN_ON(memhandle != VCHI_MEM_HANDLE_INVALID);
|
||||
bi = malloc(sizeof(*bi), M_VCPAGELIST, M_WAITOK | M_ZERO);
|
||||
if (bi == NULL)
|
||||
return VCHIQ_ERROR;
|
||||
|
||||
ret = create_pagelist((char __user *)offset, size,
|
||||
(dir == VCHIQ_BULK_RECEIVE)
|
||||
? PAGELIST_READ
|
||||
: PAGELIST_WRITE,
|
||||
current,
|
||||
bi);
|
||||
if (ret != 0)
|
||||
return VCHIQ_ERROR;
|
||||
|
||||
bulk->handle = memhandle;
|
||||
bulk->data = VCHIQ_ARM_ADDRESS(bi->pagelist);
|
||||
|
||||
/* Store the pagelist address in remote_data, which isn't used by the
|
||||
slave. */
|
||||
bulk->remote_data = bi;
|
||||
|
||||
return VCHIQ_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
vchiq_complete_bulk(VCHIQ_BULK_T *bulk)
|
||||
{
|
||||
if (bulk && bulk->remote_data && bulk->actual)
|
||||
free_pagelist((BULKINFO_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.
|
||||
*/
|
||||
BUG();
|
||||
}
|
||||
|
||||
void
|
||||
vchiq_dump_platform_state(void *dump_context)
|
||||
{
|
||||
char buf[80];
|
||||
int len;
|
||||
len = snprintf(buf, sizeof(buf),
|
||||
" Platform: 2835 (VC master)");
|
||||
vchiq_dump(dump_context, buf, len + 1);
|
||||
}
|
||||
|
||||
VCHIQ_STATUS_T
|
||||
vchiq_platform_suspend(VCHIQ_STATE_T *state)
|
||||
{
|
||||
return VCHIQ_ERROR;
|
||||
}
|
||||
|
||||
VCHIQ_STATUS_T
|
||||
vchiq_platform_resume(VCHIQ_STATE_T *state)
|
||||
{
|
||||
return VCHIQ_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
vchiq_platform_paused(VCHIQ_STATE_T *state)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
vchiq_platform_resumed(VCHIQ_STATE_T *state)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
vchiq_platform_videocore_wanted(VCHIQ_STATE_T* state)
|
||||
{
|
||||
return 1; // autosuspend not supported - videocore always wanted
|
||||
}
|
||||
|
||||
int
|
||||
vchiq_platform_use_suspend_timer(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void
|
||||
vchiq_dump_platform_use_state(VCHIQ_STATE_T *state)
|
||||
{
|
||||
vchiq_log_info(vchiq_arm_log_level, "Suspend timer not in use");
|
||||
}
|
||||
void
|
||||
vchiq_platform_handle_timeout(VCHIQ_STATE_T *state)
|
||||
{
|
||||
(void)state;
|
||||
}
|
||||
/*
|
||||
* Local functions
|
||||
*/
|
||||
|
||||
/* 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 proc *p, BULKINFO_T *bi)
|
||||
{
|
||||
PAGELIST_T *pagelist;
|
||||
vm_page_t* pages;
|
||||
unsigned long *addrs;
|
||||
unsigned int num_pages, i;
|
||||
vm_offset_t offset;
|
||||
int pagelist_size;
|
||||
char *addr, *base_addr, *next_addr;
|
||||
int run, addridx, actual_pages;
|
||||
int err;
|
||||
vm_paddr_t pagelist_phys;
|
||||
|
||||
offset = (vm_offset_t)buf & (PAGE_SIZE - 1);
|
||||
num_pages = (count + offset + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
|
||||
bi->pagelist = NULL;
|
||||
bi->buf = buf;
|
||||
bi->size = count;
|
||||
|
||||
/* Allocate enough storage to hold the page pointers and the page
|
||||
** list
|
||||
*/
|
||||
pagelist_size = sizeof(PAGELIST_T) +
|
||||
(num_pages * sizeof(unsigned long)) +
|
||||
(num_pages * sizeof(pages[0]));
|
||||
|
||||
err = bus_dma_tag_create(
|
||||
NULL,
|
||||
PAGE_SIZE, 0, /* alignment, boundary */
|
||||
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
pagelist_size, 1, /* maxsize, nsegments */
|
||||
pagelist_size, 0, /* maxsegsize, flags */
|
||||
NULL, NULL, /* lockfunc, lockarg */
|
||||
&bi->pagelist_dma_tag);
|
||||
|
||||
|
||||
|
||||
err = bus_dmamem_alloc(bi->pagelist_dma_tag, (void **)&pagelist,
|
||||
BUS_DMA_COHERENT | BUS_DMA_WAITOK, &bi->pagelist_dma_map);
|
||||
if (err) {
|
||||
vchiq_log_error(vchiq_core_log_level, "Unable to allocate pagelist memory");
|
||||
err = -ENOMEM;
|
||||
goto failed_alloc;
|
||||
}
|
||||
|
||||
err = bus_dmamap_load(bi->pagelist_dma_tag, bi->pagelist_dma_map, pagelist,
|
||||
pagelist_size, vchiq_dmamap_cb,
|
||||
&pagelist_phys, 0);
|
||||
|
||||
if (err) {
|
||||
vchiq_log_error(vchiq_core_log_level, "cannot load DMA map for pagelist memory");
|
||||
err = -ENOMEM;
|
||||
goto failed_load;
|
||||
}
|
||||
|
||||
vchiq_log_trace(vchiq_arm_log_level,
|
||||
"create_pagelist - %x", (unsigned int)pagelist);
|
||||
if (!pagelist)
|
||||
return -ENOMEM;
|
||||
|
||||
addrs = pagelist->addrs;
|
||||
pages = (vm_page_t*)(addrs + num_pages);
|
||||
|
||||
actual_pages = vm_fault_quick_hold_pages(&p->p_vmspace->vm_map,
|
||||
(vm_offset_t)buf, count,
|
||||
(type == PAGELIST_READ ? VM_PROT_WRITE : 0 ) | VM_PROT_READ, pages, num_pages);
|
||||
|
||||
if (actual_pages != num_pages) {
|
||||
vm_page_unhold_pages(pages, actual_pages);
|
||||
free(pagelist, M_VCPAGELIST);
|
||||
return (-ENOMEM);
|
||||
}
|
||||
|
||||
pagelist->length = count;
|
||||
pagelist->type = type;
|
||||
pagelist->offset = offset;
|
||||
|
||||
/* Group the pages into runs of contiguous pages */
|
||||
|
||||
base_addr = (void *)PHYS_TO_VCBUS(VM_PAGE_TO_PHYS(pages[0]));
|
||||
next_addr = base_addr + PAGE_SIZE;
|
||||
addridx = 0;
|
||||
run = 0;
|
||||
|
||||
for (i = 1; i < num_pages; i++) {
|
||||
addr = (void *)PHYS_TO_VCBUS(VM_PAGE_TO_PHYS(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) {
|
||||
free(pagelist, M_VCPAGELIST);
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
WARN_ON(g_free_fragments == NULL);
|
||||
|
||||
down(&g_free_fragments_mutex);
|
||||
fragments = (FRAGMENTS_T *) g_free_fragments;
|
||||
WARN_ON(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);
|
||||
}
|
||||
|
||||
/* XXX: optimize? INV operation for read WBINV for write? */
|
||||
cpu_dcache_wbinv_range((vm_offset_t)buf, count);
|
||||
|
||||
bi->pagelist = pagelist;
|
||||
|
||||
return 0;
|
||||
|
||||
failed_load:
|
||||
bus_dmamap_unload(bi->pagelist_dma_tag, bi->pagelist_dma_map);
|
||||
failed_alloc:
|
||||
bus_dmamap_destroy(bi->pagelist_dma_tag, bi->pagelist_dma_map);
|
||||
bus_dma_tag_destroy(bi->pagelist_dma_tag);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
free_pagelist(BULKINFO_T *bi, int actual)
|
||||
{
|
||||
vm_page_t*pages;
|
||||
unsigned int num_pages, i;
|
||||
void *page_address;
|
||||
PAGELIST_T *pagelist;
|
||||
|
||||
pagelist = bi->pagelist;
|
||||
|
||||
vchiq_log_trace(vchiq_arm_log_level,
|
||||
"free_pagelist - %x, %d", (unsigned int)pagelist, actual);
|
||||
|
||||
num_pages =
|
||||
(pagelist->length + pagelist->offset + PAGE_SIZE - 1) /
|
||||
PAGE_SIZE;
|
||||
|
||||
pages = (vm_page_t*)(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;
|
||||
head_bytes = (CACHE_LINE_SIZE - pagelist->offset) &
|
||||
(CACHE_LINE_SIZE - 1);
|
||||
tail_bytes = (pagelist->offset + actual) &
|
||||
(CACHE_LINE_SIZE - 1);
|
||||
|
||||
if ((actual >= 0) && (head_bytes != 0)) {
|
||||
if (head_bytes > actual)
|
||||
head_bytes = actual;
|
||||
|
||||
memcpy((char *)bi->buf,
|
||||
fragments->headbuf,
|
||||
head_bytes);
|
||||
}
|
||||
|
||||
if ((actual >= 0) && (head_bytes < actual) &&
|
||||
(tail_bytes != 0)) {
|
||||
memcpy((char *)bi->buf + actual - tail_bytes,
|
||||
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)
|
||||
vm_page_dirty(pages[i]);
|
||||
}
|
||||
|
||||
vm_page_unhold_pages(pages, num_pages);
|
||||
|
||||
bus_dmamap_unload(bi->pagelist_dma_tag, bi->pagelist_dma_map);
|
||||
bus_dmamem_free(bi->pagelist_dma_tag, bi->pagelist, bi->pagelist_dma_map);
|
||||
bus_dmamap_destroy(bi->pagelist_dma_tag, bi->pagelist_dma_map);
|
||||
bus_dma_tag_destroy(bi->pagelist_dma_tag);
|
||||
|
||||
free(bi, M_VCPAGELIST);
|
||||
}
|
2810
sys/contrib/vchiq/interface/vchiq_arm/vchiq_arm.c
Normal file
2810
sys/contrib/vchiq/interface/vchiq_arm/vchiq_arm.c
Normal file
File diff suppressed because it is too large
Load Diff
200
sys/contrib/vchiq/interface/vchiq_arm/vchiq_arm.h
Normal file
200
sys/contrib/vchiq/interface/vchiq_arm/vchiq_arm.h
Normal file
@ -0,0 +1,200 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef VCHIQ_ARM_H
|
||||
#define VCHIQ_ARM_H
|
||||
|
||||
#include "vchiq_core.h"
|
||||
|
||||
|
||||
enum vc_suspend_status {
|
||||
VC_SUSPEND_FORCE_CANCELED = -3, /* Force suspend canceled, too busy */
|
||||
VC_SUSPEND_REJECTED = -2, /* Videocore rejected suspend request */
|
||||
VC_SUSPEND_FAILED = -1, /* Videocore suspend failed */
|
||||
VC_SUSPEND_IDLE = 0, /* VC active, no suspend actions */
|
||||
VC_SUSPEND_REQUESTED, /* User has requested suspend */
|
||||
VC_SUSPEND_IN_PROGRESS, /* Slot handler has recvd suspend request */
|
||||
VC_SUSPEND_SUSPENDED /* Videocore suspend succeeded */
|
||||
};
|
||||
|
||||
enum vc_resume_status {
|
||||
VC_RESUME_FAILED = -1, /* Videocore resume failed */
|
||||
VC_RESUME_IDLE = 0, /* VC suspended, no resume actions */
|
||||
VC_RESUME_REQUESTED, /* User has requested resume */
|
||||
VC_RESUME_IN_PROGRESS, /* Slot handler has received resume request */
|
||||
VC_RESUME_RESUMED /* Videocore resumed successfully (active) */
|
||||
};
|
||||
|
||||
|
||||
enum USE_TYPE_E {
|
||||
USE_TYPE_SERVICE,
|
||||
USE_TYPE_SERVICE_NO_RESUME,
|
||||
USE_TYPE_VCHIQ
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef struct vchiq_arm_state_struct {
|
||||
/* Keepalive-related data */
|
||||
VCHIQ_THREAD_T ka_thread;
|
||||
struct completion ka_evt;
|
||||
atomic_t ka_use_count;
|
||||
atomic_t ka_use_ack_count;
|
||||
atomic_t ka_release_count;
|
||||
|
||||
struct completion vc_suspend_complete;
|
||||
struct completion vc_resume_complete;
|
||||
|
||||
rwlock_t susp_res_lock;
|
||||
enum vc_suspend_status vc_suspend_state;
|
||||
enum vc_resume_status vc_resume_state;
|
||||
|
||||
unsigned int wake_address;
|
||||
|
||||
struct timer_list suspend_timer;
|
||||
int suspend_timer_timeout;
|
||||
int suspend_timer_running;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Use count to track requests from videocore peer.
|
||||
** This use count is not associated with a service, so needs to be
|
||||
** tracked separately with the state.
|
||||
*/
|
||||
int peer_use_count;
|
||||
|
||||
/* Flag to indicate whether resume is blocked. This happens when the
|
||||
** ARM is suspending
|
||||
*/
|
||||
struct completion resume_blocker;
|
||||
int resume_blocked;
|
||||
struct completion blocked_blocker;
|
||||
int blocked_count;
|
||||
|
||||
int autosuspend_override;
|
||||
|
||||
/* Flag to indicate that the first vchiq connect has made it through.
|
||||
** This means that both sides should be fully ready, and we should
|
||||
** be able to suspend after this point.
|
||||
*/
|
||||
int first_connect;
|
||||
|
||||
unsigned long long suspend_start_time;
|
||||
unsigned long long sleep_start_time;
|
||||
unsigned long long resume_start_time;
|
||||
unsigned long long last_wake_time;
|
||||
|
||||
} VCHIQ_ARM_STATE_T;
|
||||
|
||||
extern int vchiq_arm_log_level;
|
||||
extern int vchiq_susp_log_level;
|
||||
|
||||
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);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_arm_vcsuspend(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_arm_force_suspend(VCHIQ_STATE_T *state);
|
||||
|
||||
extern int
|
||||
vchiq_arm_allow_resume(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_arm_vcresume(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state);
|
||||
|
||||
extern int
|
||||
vchiq_check_resume(VCHIQ_STATE_T *state);
|
||||
|
||||
extern void
|
||||
vchiq_check_suspend(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_platform_suspend(VCHIQ_STATE_T *state);
|
||||
|
||||
extern int
|
||||
vchiq_platform_videocore_wanted(VCHIQ_STATE_T *state);
|
||||
|
||||
extern int
|
||||
vchiq_platform_use_suspend_timer(void);
|
||||
|
||||
extern void
|
||||
vchiq_dump_platform_use_state(VCHIQ_STATE_T *state);
|
||||
|
||||
extern void
|
||||
vchiq_dump_service_use_state(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_ARM_STATE_T*
|
||||
vchiq_platform_get_arm_state(VCHIQ_STATE_T *state);
|
||||
|
||||
extern int
|
||||
vchiq_videocore_wanted(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_use_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
|
||||
enum USE_TYPE_E use_type);
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_release_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service);
|
||||
|
||||
void
|
||||
set_suspend_state(VCHIQ_ARM_STATE_T *arm_state,
|
||||
enum vc_suspend_status new_state);
|
||||
|
||||
void
|
||||
set_resume_state(VCHIQ_ARM_STATE_T *arm_state,
|
||||
enum vc_resume_status new_state);
|
||||
|
||||
void
|
||||
start_suspend_timer(VCHIQ_ARM_STATE_T *arm_state);
|
||||
|
||||
extern int vchiq_proc_init(void);
|
||||
extern void vchiq_proc_deinit(void);
|
||||
extern struct proc_dir_entry *vchiq_proc_top(void);
|
||||
extern struct proc_dir_entry *vchiq_clients_top(void);
|
||||
|
||||
|
||||
#endif /* VCHIQ_ARM_H */
|
37
sys/contrib/vchiq/interface/vchiq_arm/vchiq_build_info.h
Normal file
37
sys/contrib/vchiq/interface/vchiq_arm/vchiq_build_info.h
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
const char *vchiq_get_build_hostname(void);
|
||||
const char *vchiq_get_build_version(void);
|
||||
const char *vchiq_get_build_time(void);
|
||||
const char *vchiq_get_build_date(void);
|
60
sys/contrib/vchiq/interface/vchiq_arm/vchiq_cfg.h
Normal file
60
sys/contrib/vchiq/interface/vchiq_arm/vchiq_cfg.h
Normal file
@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef 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 6
|
||||
/* The minimum compatible version - update to match VCHIQ_VERSION with any
|
||||
** incompatible change */
|
||||
#define VCHIQ_VERSION_MIN 3
|
||||
|
||||
#define VCHIQ_MAX_STATES 1
|
||||
#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 */
|
117
sys/contrib/vchiq/interface/vchiq_arm/vchiq_connected.c
Normal file
117
sys/contrib/vchiq/interface/vchiq_arm/vchiq_connected.c
Normal file
@ -0,0 +1,117 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "vchiq_connected.h"
|
||||
#include "vchiq_core.h"
|
||||
|
||||
#define MAX_CALLBACKS 10
|
||||
|
||||
static int g_connected;
|
||||
static int g_num_deferred_callbacks;
|
||||
static VCHIQ_CONNECTED_CALLBACK_T g_deferred_callback[MAX_CALLBACKS];
|
||||
static int g_once_init;
|
||||
static struct mutex g_connected_mutex;
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Function to initialize our lock.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
static void connected_init(void)
|
||||
{
|
||||
if (!g_once_init) {
|
||||
lmutex_init(&g_connected_mutex);
|
||||
g_once_init = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
connected_init();
|
||||
|
||||
if (lmutex_lock_interruptible(&g_connected_mutex) != 0)
|
||||
return;
|
||||
|
||||
if (g_connected)
|
||||
/* We're already connected. Call the callback immediately. */
|
||||
|
||||
callback();
|
||||
else {
|
||||
if (g_num_deferred_callbacks >= MAX_CALLBACKS)
|
||||
vchiq_log_error(vchiq_core_log_level,
|
||||
"There are already %d callbacks registered - "
|
||||
"please increase MAX_CALLBACKS",
|
||||
g_num_deferred_callbacks);
|
||||
else {
|
||||
g_deferred_callback[g_num_deferred_callbacks] =
|
||||
callback;
|
||||
g_num_deferred_callbacks++;
|
||||
}
|
||||
}
|
||||
lmutex_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;
|
||||
|
||||
connected_init();
|
||||
|
||||
if (lmutex_lock_interruptible(&g_connected_mutex) != 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < g_num_deferred_callbacks; i++)
|
||||
g_deferred_callback[i]();
|
||||
|
||||
g_num_deferred_callbacks = 0;
|
||||
g_connected = 1;
|
||||
lmutex_unlock(&g_connected_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_add_connected_callback);
|
51
sys/contrib/vchiq/interface/vchiq_arm/vchiq_connected.h
Normal file
51
sys/contrib/vchiq/interface/vchiq_arm/vchiq_connected.h
Normal file
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef 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 */
|
||||
|
3842
sys/contrib/vchiq/interface/vchiq_arm/vchiq_core.c
Normal file
3842
sys/contrib/vchiq/interface/vchiq_arm/vchiq_core.c
Normal file
File diff suppressed because it is too large
Load Diff
710
sys/contrib/vchiq/interface/vchiq_arm/vchiq_core.h
Normal file
710
sys/contrib/vchiq/interface/vchiq_arm/vchiq_core.h
Normal file
@ -0,0 +1,710 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef VCHIQ_CORE_H
|
||||
#define VCHIQ_CORE_H
|
||||
|
||||
#include <interface/compat/vchi_bsd.h>
|
||||
#include <interface/compat/list.h>
|
||||
|
||||
#include "vchiq_cfg.h"
|
||||
|
||||
#include "vchiq.h"
|
||||
|
||||
/* Run time control of log level, based on KERN_XXX level. */
|
||||
#ifndef VCHIQ_LOG_DEFAULT
|
||||
#define VCHIQ_LOG_DEFAULT 4
|
||||
#endif
|
||||
#define VCHIQ_LOG_ERROR 3
|
||||
#define VCHIQ_LOG_WARNING 4
|
||||
#define VCHIQ_LOG_INFO 6
|
||||
#define VCHIQ_LOG_TRACE 7
|
||||
|
||||
#define VCHIQ_LOG_PREFIX "vchiq: "
|
||||
|
||||
#ifndef vchiq_log_error
|
||||
#define vchiq_log_error(cat, fmt, ...) \
|
||||
do { if (cat >= VCHIQ_LOG_ERROR) \
|
||||
printf(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)
|
||||
#endif
|
||||
#ifndef vchiq_log_warning
|
||||
#define vchiq_log_warning(cat, fmt, ...) \
|
||||
do { if (cat >= VCHIQ_LOG_WARNING) \
|
||||
printf(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)
|
||||
#endif
|
||||
#ifndef vchiq_log_info
|
||||
#define vchiq_log_info(cat, fmt, ...) \
|
||||
do { if (cat >= VCHIQ_LOG_INFO) \
|
||||
printf(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)
|
||||
#endif
|
||||
#ifndef vchiq_log_trace
|
||||
#define vchiq_log_trace(cat, fmt, ...) \
|
||||
do { if (cat >= VCHIQ_LOG_TRACE) \
|
||||
printf(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)
|
||||
#endif
|
||||
|
||||
#define vchiq_loud_error(...) \
|
||||
vchiq_log_error(vchiq_core_log_level, "===== " __VA_ARGS__)
|
||||
|
||||
#ifndef vchiq_static_assert
|
||||
#define vchiq_static_assert(cond) __attribute__((unused)) \
|
||||
extern int vchiq_static_assert[(cond) ? 1 : -1]
|
||||
#endif
|
||||
|
||||
#define IS_POW2(x) (x && ((x & (x - 1)) == 0))
|
||||
|
||||
/* Ensure that the slot size and maximum number of slots are powers of 2 */
|
||||
vchiq_static_assert(IS_POW2(VCHIQ_SLOT_SIZE));
|
||||
vchiq_static_assert(IS_POW2(VCHIQ_MAX_SLOTS));
|
||||
vchiq_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_MSG_REMOTE_USE 12 /* - */
|
||||
#define VCHIQ_MSG_REMOTE_RELEASE 13 /* - */
|
||||
#define VCHIQ_MSG_REMOTE_USE_ACTIVE 14 /* - */
|
||||
|
||||
#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 */
|
||||
vchiq_static_assert(VCHIQ_MSG_SRCPORT(VCHIQ_MAKE_MSG(0, 0, VCHIQ_PORT_MAX))
|
||||
== 0);
|
||||
vchiq_static_assert(VCHIQ_MSG_TYPE(VCHIQ_MAKE_MSG(0, VCHIQ_PORT_MAX, 0)) == 0);
|
||||
vchiq_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;
|
||||
|
||||
vchiq_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) int *debug_ptr = (local)->debug;
|
||||
#define DEBUG_TRACE(d) \
|
||||
do { debug_ptr[DEBUG_ ## d] = __LINE__; dsb(); } while (0)
|
||||
#define DEBUG_VALUE(d, v) \
|
||||
do { debug_ptr[DEBUG_ ## d] = (v); dsb(); } while (0)
|
||||
#define DEBUG_COUNT(d) \
|
||||
do { debug_ptr[DEBUG_ ## d]++; dsb(); } while (0)
|
||||
|
||||
#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_CONNECTING,
|
||||
VCHIQ_CONNSTATE_CONNECTED,
|
||||
VCHIQ_CONNSTATE_PAUSING,
|
||||
VCHIQ_CONNSTATE_PAUSE_SENT,
|
||||
VCHIQ_CONNSTATE_PAUSED,
|
||||
VCHIQ_CONNSTATE_RESUMING,
|
||||
VCHIQ_CONNSTATE_PAUSE_TIMEOUT,
|
||||
VCHIQ_CONNSTATE_RESUME_TIMEOUT
|
||||
} VCHIQ_CONNSTATE_T;
|
||||
|
||||
enum {
|
||||
VCHIQ_SRVSTATE_FREE,
|
||||
VCHIQ_SRVSTATE_HIDDEN,
|
||||
VCHIQ_SRVSTATE_LISTENING,
|
||||
VCHIQ_SRVSTATE_OPENING,
|
||||
VCHIQ_SRVSTATE_OPEN,
|
||||
VCHIQ_SRVSTATE_OPENSYNC,
|
||||
VCHIQ_SRVSTATE_CLOSESENT,
|
||||
VCHIQ_SRVSTATE_CLOSERECVD,
|
||||
VCHIQ_SRVSTATE_CLOSEWAIT,
|
||||
VCHIQ_SRVSTATE_CLOSED
|
||||
};
|
||||
|
||||
enum {
|
||||
VCHIQ_POLL_TERMINATE,
|
||||
VCHIQ_POLL_REMOVE,
|
||||
VCHIQ_POLL_TXNOTIFY,
|
||||
VCHIQ_POLL_RXNOTIFY,
|
||||
VCHIQ_POLL_COUNT
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
VCHIQ_BULK_TRANSMIT,
|
||||
VCHIQ_BULK_RECEIVE
|
||||
} VCHIQ_BULK_DIR_T;
|
||||
|
||||
typedef void (*VCHIQ_USERDATA_TERM_T)(void *userdata);
|
||||
|
||||
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 (mstr) */
|
||||
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 {
|
||||
int armed;
|
||||
int fired;
|
||||
struct semaphore *event;
|
||||
} REMOTE_EVENT_T;
|
||||
|
||||
typedef struct opaque_platform_state_t *VCHIQ_PLATFORM_STATE_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. */
|
||||
short use_count;
|
||||
short release_count;
|
||||
} __packed VCHIQ_SLOT_INFO_T; /* XXXGONZO: check it */
|
||||
|
||||
typedef struct vchiq_service_struct {
|
||||
VCHIQ_SERVICE_BASE_T base;
|
||||
VCHIQ_SERVICE_HANDLE_T handle;
|
||||
unsigned int ref_count;
|
||||
int srvstate;
|
||||
VCHIQ_USERDATA_TERM_T userdata_term;
|
||||
unsigned int localport;
|
||||
unsigned int remoteport;
|
||||
int public_fourcc;
|
||||
int client_id;
|
||||
char auto_close;
|
||||
char sync;
|
||||
char closing;
|
||||
atomic_t poll_flags;
|
||||
short version;
|
||||
short version_min;
|
||||
short peer_version;
|
||||
|
||||
VCHIQ_STATE_T *state;
|
||||
VCHIQ_INSTANCE_T instance;
|
||||
|
||||
int service_use_count;
|
||||
|
||||
VCHIQ_BULK_QUEUE_T bulk_tx;
|
||||
VCHIQ_BULK_QUEUE_T bulk_rx;
|
||||
|
||||
struct semaphore remove_event;
|
||||
struct semaphore bulk_remove_event;
|
||||
struct mutex 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 {
|
||||
unsigned short slot_quota;
|
||||
unsigned short slot_use_count;
|
||||
unsigned short message_quota;
|
||||
unsigned short message_use_count;
|
||||
struct semaphore 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;
|
||||
|
||||
/* The slot allocated to synchronous messages from the owner. */
|
||||
int slot_sync;
|
||||
|
||||
/* 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. */
|
||||
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. */
|
||||
int slot_queue_recycle;
|
||||
|
||||
/* This event should be signalled when a synchronous message is sent. */
|
||||
REMOTE_EVENT_T sync_trigger;
|
||||
|
||||
/* This event should be signalled when a synchronous message has been
|
||||
** released. */
|
||||
REMOTE_EVENT_T sync_release;
|
||||
|
||||
/* A circular buffer of slot indexes. */
|
||||
int slot_queue[VCHIQ_MAX_SLOTS_PER_SIDE];
|
||||
|
||||
/* Debugging state */
|
||||
int debug[DEBUG_MAX];
|
||||
} __packed 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];
|
||||
} __packed 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;
|
||||
|
||||
unsigned short default_slot_quota;
|
||||
unsigned short default_message_quota;
|
||||
|
||||
/* Event indicating connect message received */
|
||||
struct semaphore connect;
|
||||
|
||||
/* Mutex protecting services */
|
||||
struct mutex mutex;
|
||||
VCHIQ_INSTANCE_T *instance;
|
||||
|
||||
/* Processes incoming messages */
|
||||
VCHIQ_THREAD_T slot_handler_thread;
|
||||
|
||||
/* Processes recycled slots */
|
||||
VCHIQ_THREAD_T recycle_thread;
|
||||
|
||||
/* Processes synchronous messages */
|
||||
VCHIQ_THREAD_T sync_thread;
|
||||
|
||||
/* Local implementation of the trigger remote event */
|
||||
struct semaphore trigger_event;
|
||||
|
||||
/* Local implementation of the recycle remote event */
|
||||
struct semaphore recycle_event;
|
||||
|
||||
/* Local implementation of the sync trigger remote event */
|
||||
struct semaphore sync_trigger_event;
|
||||
|
||||
/* Local implementation of the sync release remote event */
|
||||
struct semaphore sync_release_event;
|
||||
|
||||
char *tx_data;
|
||||
char *rx_data;
|
||||
VCHIQ_SLOT_INFO_T *rx_info;
|
||||
|
||||
struct mutex slot_mutex;
|
||||
|
||||
struct mutex recycle_mutex;
|
||||
|
||||
struct mutex sync_mutex;
|
||||
|
||||
struct mutex bulk_transfer_mutex;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Ths index of the previous slot used for data messages. */
|
||||
int previous_data_index;
|
||||
|
||||
/* The number of slots occupied by data messages. */
|
||||
unsigned short data_use_count;
|
||||
|
||||
/* The maximum number of slots to be occupied by data messages. */
|
||||
unsigned short data_quota;
|
||||
|
||||
/* An array of bit sets indicating which services must be polled. */
|
||||
atomic_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. */
|
||||
struct semaphore slot_available_event;
|
||||
|
||||
struct semaphore slot_remove_event;
|
||||
|
||||
/* Signalled when a free data slot becomes available. */
|
||||
struct semaphore data_quota_event;
|
||||
|
||||
/* Incremented when there are bulk transfers which cannot be processed
|
||||
* whilst paused and must be processed on resume */
|
||||
int deferred_bulks;
|
||||
|
||||
struct state_stats_struct {
|
||||
int slot_stalls;
|
||||
int data_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];
|
||||
|
||||
VCHIQ_PLATFORM_STATE_T platform_state;
|
||||
};
|
||||
|
||||
struct bulk_waiter {
|
||||
VCHIQ_BULK_T *bulk;
|
||||
struct semaphore event;
|
||||
int actual;
|
||||
};
|
||||
|
||||
extern spinlock_t bulk_waiter_spinlock;
|
||||
|
||||
extern int vchiq_core_log_level;
|
||||
extern int vchiq_core_msg_log_level;
|
||||
extern int vchiq_sync_log_level;
|
||||
|
||||
extern VCHIQ_STATE_T *vchiq_states[VCHIQ_MAX_STATES];
|
||||
|
||||
extern const char *
|
||||
get_conn_state_name(VCHIQ_CONNSTATE_T conn_state);
|
||||
|
||||
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, VCHIQ_USERDATA_TERM_T userdata_term);
|
||||
|
||||
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_HANDLE_T handle,
|
||||
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);
|
||||
|
||||
extern void
|
||||
vchiq_loud_error_header(void);
|
||||
|
||||
extern void
|
||||
vchiq_loud_error_footer(void);
|
||||
|
||||
extern void
|
||||
request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type);
|
||||
|
||||
static inline VCHIQ_SERVICE_T *
|
||||
handle_to_service(VCHIQ_SERVICE_HANDLE_T handle)
|
||||
{
|
||||
VCHIQ_STATE_T *state = vchiq_states[(handle / VCHIQ_MAX_SERVICES) &
|
||||
(VCHIQ_MAX_STATES - 1)];
|
||||
if (!state)
|
||||
return NULL;
|
||||
|
||||
return state->services[handle & (VCHIQ_MAX_SERVICES - 1)];
|
||||
}
|
||||
|
||||
extern VCHIQ_SERVICE_T *
|
||||
find_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle);
|
||||
|
||||
extern VCHIQ_SERVICE_T *
|
||||
find_service_by_port(VCHIQ_STATE_T *state, int localport);
|
||||
|
||||
extern VCHIQ_SERVICE_T *
|
||||
find_service_for_instance(VCHIQ_INSTANCE_T instance,
|
||||
VCHIQ_SERVICE_HANDLE_T handle);
|
||||
|
||||
extern VCHIQ_SERVICE_T *
|
||||
next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance,
|
||||
int *pidx);
|
||||
|
||||
extern void
|
||||
lock_service(VCHIQ_SERVICE_T *service);
|
||||
|
||||
extern void
|
||||
unlock_service(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);
|
||||
|
||||
void
|
||||
vchiq_platform_check_suspend(VCHIQ_STATE_T *state);
|
||||
|
||||
extern void
|
||||
vchiq_platform_paused(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_platform_resume(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);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_use_service_internal(VCHIQ_SERVICE_T *service);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_release_service_internal(VCHIQ_SERVICE_T *service);
|
||||
|
||||
extern void
|
||||
vchiq_on_remote_use(VCHIQ_STATE_T *state);
|
||||
|
||||
extern void
|
||||
vchiq_on_remote_release(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_platform_init_state(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_check_service(VCHIQ_SERVICE_T *service);
|
||||
|
||||
extern void
|
||||
vchiq_on_remote_use_active(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_send_remote_use(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_send_remote_release(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_send_remote_use_active(VCHIQ_STATE_T *state);
|
||||
|
||||
extern void
|
||||
vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state,
|
||||
VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate);
|
||||
|
||||
extern void
|
||||
vchiq_platform_handle_timeout(VCHIQ_STATE_T *state);
|
||||
|
||||
extern void
|
||||
vchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate);
|
||||
|
||||
|
||||
extern void
|
||||
vchiq_log_dump_mem(const char *label, uint32_t addr, const void *voidMem,
|
||||
size_t numBytes);
|
||||
|
||||
extern void
|
||||
vchiq_core_initialize(void);
|
||||
|
||||
#endif
|
188
sys/contrib/vchiq/interface/vchiq_arm/vchiq_if.h
Normal file
188
sys/contrib/vchiq/interface/vchiq_arm/vchiq_if.h
Normal file
@ -0,0 +1,188 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef VCHIQ_IF_H
|
||||
#define VCHIQ_IF_H
|
||||
|
||||
#include "interface/vchi/vchi_mh.h"
|
||||
|
||||
#define VCHIQ_SERVICE_HANDLE_INVALID 0
|
||||
|
||||
#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) vchiq_get_service_userdata(service)
|
||||
#define VCHIQ_GET_SERVICE_FOURCC(service) vchiq_get_service_fourcc(service)
|
||||
|
||||
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_WAITING /* Reserved for internal use */
|
||||
} VCHIQ_BULK_MODE_T;
|
||||
|
||||
typedef enum {
|
||||
VCHIQ_SERVICE_OPTION_AUTOCLOSE,
|
||||
VCHIQ_SERVICE_OPTION_SLOT_QUOTA,
|
||||
VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA,
|
||||
VCHIQ_SERVICE_OPTION_SYNCHRONOUS
|
||||
} VCHIQ_SERVICE_OPTION_T;
|
||||
|
||||
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;
|
||||
|
||||
typedef struct {
|
||||
const void *data;
|
||||
unsigned int size;
|
||||
} VCHIQ_ELEMENT_T;
|
||||
|
||||
typedef unsigned int 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 {
|
||||
unsigned int max_msg_size;
|
||||
unsigned int bulk_threshold; /* The message size above which it
|
||||
is better to use a bulk transfer
|
||||
(<= max_msg_size) */
|
||||
unsigned int max_outstanding_bulks;
|
||||
unsigned 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;
|
||||
typedef void (*VCHIQ_REMOTE_USE_CALLBACK_T)(void *cb_arg);
|
||||
|
||||
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,
|
||||
const VCHIQ_SERVICE_PARAMS_T *params,
|
||||
VCHIQ_SERVICE_HANDLE_T *pservice);
|
||||
extern VCHIQ_STATUS_T vchiq_open_service(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_use_service_no_resume(
|
||||
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, unsigned 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,
|
||||
void *data, unsigned int size, void *userdata);
|
||||
extern VCHIQ_STATUS_T vchiq_queue_bulk_receive(VCHIQ_SERVICE_HANDLE_T service,
|
||||
void *data, unsigned 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, unsigned 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, unsigned int size, void *userdata);
|
||||
extern VCHIQ_STATUS_T vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T service,
|
||||
void *data, unsigned int size, void *userdata,
|
||||
VCHIQ_BULK_MODE_T mode);
|
||||
extern VCHIQ_STATUS_T vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T service,
|
||||
void *data, unsigned 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, unsigned 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, unsigned int size,
|
||||
void *userdata, VCHIQ_BULK_MODE_T mode);
|
||||
extern int vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T service);
|
||||
extern void *vchiq_get_service_userdata(VCHIQ_SERVICE_HANDLE_T service);
|
||||
extern int vchiq_get_service_fourcc(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_remote_use(VCHIQ_INSTANCE_T instance,
|
||||
VCHIQ_REMOTE_USE_CALLBACK_T callback, void *cb_arg);
|
||||
extern VCHIQ_STATUS_T vchiq_remote_release(VCHIQ_INSTANCE_T instance);
|
||||
|
||||
extern VCHIQ_STATUS_T vchiq_dump_phys_mem(VCHIQ_SERVICE_HANDLE_T service,
|
||||
void *ptr, size_t num_bytes);
|
||||
|
||||
extern VCHIQ_STATUS_T vchiq_get_peer_version(VCHIQ_SERVICE_HANDLE_T handle,
|
||||
short *peer_version);
|
||||
|
||||
#endif /* VCHIQ_IF_H */
|
128
sys/contrib/vchiq/interface/vchiq_arm/vchiq_ioctl.h
Normal file
128
sys/contrib/vchiq/interface/vchiq_arm/vchiq_ioctl.h
Normal file
@ -0,0 +1,128 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef VCHIQ_IOCTLS_H
|
||||
#define VCHIQ_IOCTLS_H
|
||||
|
||||
#include "vchiq_if.h"
|
||||
|
||||
#define VCHIQ_IOC_MAGIC 0xc4
|
||||
#define VCHIQ_INVALID_HANDLE (~0)
|
||||
|
||||
typedef struct {
|
||||
VCHIQ_SERVICE_PARAMS_T params;
|
||||
int is_open;
|
||||
int is_vchi;
|
||||
unsigned int handle; /* OUT */
|
||||
} VCHIQ_CREATE_SERVICE_T;
|
||||
|
||||
typedef struct {
|
||||
unsigned int handle;
|
||||
unsigned int count;
|
||||
const VCHIQ_ELEMENT_T *elements;
|
||||
} VCHIQ_QUEUE_MESSAGE_T;
|
||||
|
||||
typedef struct {
|
||||
unsigned int handle;
|
||||
void *data;
|
||||
unsigned 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 {
|
||||
unsigned int count;
|
||||
VCHIQ_COMPLETION_DATA_T *buf;
|
||||
unsigned int msgbufsize;
|
||||
unsigned int msgbufcount; /* IN/OUT */
|
||||
void **msgbufs;
|
||||
} VCHIQ_AWAIT_COMPLETION_T;
|
||||
|
||||
typedef struct {
|
||||
unsigned int handle;
|
||||
int blocking;
|
||||
unsigned int bufsize;
|
||||
void *buf;
|
||||
} VCHIQ_DEQUEUE_MESSAGE_T;
|
||||
|
||||
typedef struct {
|
||||
unsigned int config_size;
|
||||
VCHIQ_CONFIG_T *pconfig;
|
||||
} VCHIQ_GET_CONFIG_T;
|
||||
|
||||
typedef struct {
|
||||
unsigned 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 \
|
||||
_IOWR(VCHIQ_IOC_MAGIC, 5, VCHIQ_QUEUE_BULK_TRANSFER_T)
|
||||
#define VCHIQ_IOC_QUEUE_BULK_RECEIVE \
|
||||
_IOWR(VCHIQ_IOC_MAGIC, 6, VCHIQ_QUEUE_BULK_TRANSFER_T)
|
||||
#define VCHIQ_IOC_AWAIT_COMPLETION \
|
||||
_IOWR(VCHIQ_IOC_MAGIC, 7, VCHIQ_AWAIT_COMPLETION_T)
|
||||
#define VCHIQ_IOC_DEQUEUE_MESSAGE \
|
||||
_IOWR(VCHIQ_IOC_MAGIC, 8, VCHIQ_DEQUEUE_MESSAGE_T)
|
||||
#define VCHIQ_IOC_GET_CLIENT_ID _IO(VCHIQ_IOC_MAGIC, 9)
|
||||
#define VCHIQ_IOC_GET_CONFIG \
|
||||
_IOWR(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
|
461
sys/contrib/vchiq/interface/vchiq_arm/vchiq_kern_lib.c
Normal file
461
sys/contrib/vchiq/interface/vchiq_arm/vchiq_kern_lib.c
Normal file
@ -0,0 +1,461 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* ---- Include Files ---------------------------------------------------- */
|
||||
|
||||
#include "vchiq_core.h"
|
||||
#include "vchiq_arm.h"
|
||||
|
||||
/* ---- Public Variables ------------------------------------------------- */
|
||||
|
||||
/* ---- Private Constants and Types -------------------------------------- */
|
||||
|
||||
struct bulk_waiter_node {
|
||||
struct bulk_waiter bulk_waiter;
|
||||
int pid;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct vchiq_instance_struct {
|
||||
VCHIQ_STATE_T *state;
|
||||
|
||||
int connected;
|
||||
|
||||
struct list_head bulk_waiter_list;
|
||||
struct mutex bulk_waiter_list_mutex;
|
||||
};
|
||||
|
||||
static VCHIQ_STATUS_T
|
||||
vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data,
|
||||
unsigned int size, VCHIQ_BULK_DIR_T dir);
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* vchiq_initialise
|
||||
*
|
||||
***************************************************************************/
|
||||
#define VCHIQ_INIT_RETRIES 10
|
||||
VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *instanceOut)
|
||||
{
|
||||
VCHIQ_STATUS_T status = VCHIQ_ERROR;
|
||||
VCHIQ_STATE_T *state;
|
||||
VCHIQ_INSTANCE_T instance = NULL;
|
||||
int i;
|
||||
|
||||
vchiq_log_trace(vchiq_core_log_level, "%s called", __func__);
|
||||
|
||||
/* VideoCore may not be ready due to boot up timing.
|
||||
It may never be ready if kernel and firmware are mismatched, so don't block forever. */
|
||||
for (i=0; i<VCHIQ_INIT_RETRIES; i++) {
|
||||
state = vchiq_get_state();
|
||||
if (state)
|
||||
break;
|
||||
udelay(500);
|
||||
}
|
||||
if (i==VCHIQ_INIT_RETRIES) {
|
||||
vchiq_log_error(vchiq_core_log_level,
|
||||
"%s: videocore not initialized\n", __func__);
|
||||
goto failed;
|
||||
} else if (i>0) {
|
||||
vchiq_log_warning(vchiq_core_log_level,
|
||||
"%s: videocore initialized after %d retries\n", __func__, i);
|
||||
}
|
||||
|
||||
instance = kzalloc(sizeof(*instance), GFP_KERNEL);
|
||||
if (!instance) {
|
||||
vchiq_log_error(vchiq_core_log_level,
|
||||
"%s: error allocating vchiq instance\n", __func__);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
instance->connected = 0;
|
||||
instance->state = state;
|
||||
lmutex_init(&instance->bulk_waiter_list_mutex);
|
||||
INIT_LIST_HEAD(&instance->bulk_waiter_list);
|
||||
|
||||
*instanceOut = instance;
|
||||
|
||||
status = VCHIQ_SUCCESS;
|
||||
|
||||
failed:
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s(%p): returning %d", __func__, instance, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_initialise);
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* vchiq_shutdown
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance)
|
||||
{
|
||||
VCHIQ_STATUS_T status;
|
||||
VCHIQ_STATE_T *state = instance->state;
|
||||
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s(%p) called", __func__, instance);
|
||||
|
||||
if (lmutex_lock_interruptible(&state->mutex) != 0)
|
||||
return VCHIQ_RETRY;
|
||||
|
||||
/* Remove all services */
|
||||
status = vchiq_shutdown_internal(state, instance);
|
||||
|
||||
lmutex_unlock(&state->mutex);
|
||||
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s(%p): returning %d", __func__, instance, status);
|
||||
|
||||
if (status == VCHIQ_SUCCESS) {
|
||||
struct list_head *pos, *next;
|
||||
list_for_each_safe(pos, next,
|
||||
&instance->bulk_waiter_list) {
|
||||
struct bulk_waiter_node *waiter;
|
||||
waiter = list_entry(pos,
|
||||
struct bulk_waiter_node,
|
||||
list);
|
||||
list_del(pos);
|
||||
vchiq_log_info(vchiq_arm_log_level,
|
||||
"bulk_waiter - cleaned up %x "
|
||||
"for pid %d",
|
||||
(unsigned int)waiter, waiter->pid);
|
||||
_sema_destroy(&waiter->bulk_waiter.event);
|
||||
|
||||
kfree(waiter);
|
||||
}
|
||||
|
||||
lmutex_destroy(&instance->bulk_waiter_list_mutex);
|
||||
|
||||
kfree(instance);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_shutdown);
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* vchiq_is_connected
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
static 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;
|
||||
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s(%p) called", __func__, instance);
|
||||
|
||||
if (lmutex_lock_interruptible(&state->mutex) != 0) {
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s: call to lmutex_lock failed", __func__);
|
||||
status = VCHIQ_RETRY;
|
||||
goto failed;
|
||||
}
|
||||
status = vchiq_connect_internal(state, instance);
|
||||
|
||||
if (status == VCHIQ_SUCCESS)
|
||||
instance->connected = 1;
|
||||
|
||||
lmutex_unlock(&state->mutex);
|
||||
|
||||
failed:
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s(%p): returning %d", __func__, instance, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_connect);
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* vchiq_add_service
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
VCHIQ_STATUS_T vchiq_add_service(
|
||||
VCHIQ_INSTANCE_T instance,
|
||||
const VCHIQ_SERVICE_PARAMS_T *params,
|
||||
VCHIQ_SERVICE_HANDLE_T *phandle)
|
||||
{
|
||||
VCHIQ_STATUS_T status;
|
||||
VCHIQ_STATE_T *state = instance->state;
|
||||
VCHIQ_SERVICE_T *service = NULL;
|
||||
int srvstate;
|
||||
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s(%p) called", __func__, instance);
|
||||
|
||||
*phandle = VCHIQ_SERVICE_HANDLE_INVALID;
|
||||
|
||||
srvstate = vchiq_is_connected(instance)
|
||||
? VCHIQ_SRVSTATE_LISTENING
|
||||
: VCHIQ_SRVSTATE_HIDDEN;
|
||||
|
||||
service = vchiq_add_service_internal(
|
||||
state,
|
||||
params,
|
||||
srvstate,
|
||||
instance,
|
||||
NULL);
|
||||
|
||||
if (service) {
|
||||
*phandle = service->handle;
|
||||
status = VCHIQ_SUCCESS;
|
||||
} else
|
||||
status = VCHIQ_ERROR;
|
||||
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s(%p): returning %d", __func__, instance, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_add_service);
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* vchiq_open_service
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
VCHIQ_STATUS_T vchiq_open_service(
|
||||
VCHIQ_INSTANCE_T instance,
|
||||
const VCHIQ_SERVICE_PARAMS_T *params,
|
||||
VCHIQ_SERVICE_HANDLE_T *phandle)
|
||||
{
|
||||
VCHIQ_STATUS_T status = VCHIQ_ERROR;
|
||||
VCHIQ_STATE_T *state = instance->state;
|
||||
VCHIQ_SERVICE_T *service = NULL;
|
||||
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s(%p) called", __func__, instance);
|
||||
|
||||
*phandle = VCHIQ_SERVICE_HANDLE_INVALID;
|
||||
|
||||
if (!vchiq_is_connected(instance))
|
||||
goto failed;
|
||||
|
||||
service = vchiq_add_service_internal(state,
|
||||
params,
|
||||
VCHIQ_SRVSTATE_OPENING,
|
||||
instance,
|
||||
NULL);
|
||||
|
||||
if (service) {
|
||||
*phandle = service->handle;
|
||||
status = vchiq_open_service_internal(service,
|
||||
(uintptr_t)current);
|
||||
if (status != VCHIQ_SUCCESS) {
|
||||
vchiq_remove_service(service->handle);
|
||||
*phandle = VCHIQ_SERVICE_HANDLE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
failed:
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s(%p): returning %d", __func__, instance, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_open_service);
|
||||
|
||||
VCHIQ_STATUS_T
|
||||
vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle,
|
||||
void *data, unsigned int size, void *userdata)
|
||||
{
|
||||
return vchiq_bulk_transfer(handle,
|
||||
VCHI_MEM_HANDLE_INVALID, data, size, userdata,
|
||||
VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_TRANSMIT);
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_queue_bulk_transmit);
|
||||
|
||||
VCHIQ_STATUS_T
|
||||
vchiq_queue_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data,
|
||||
unsigned int size, void *userdata)
|
||||
{
|
||||
return vchiq_bulk_transfer(handle,
|
||||
VCHI_MEM_HANDLE_INVALID, data, size, userdata,
|
||||
VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_RECEIVE);
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_queue_bulk_receive);
|
||||
|
||||
VCHIQ_STATUS_T
|
||||
vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle, void *data,
|
||||
unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode)
|
||||
{
|
||||
VCHIQ_STATUS_T status;
|
||||
|
||||
switch (mode) {
|
||||
case VCHIQ_BULK_MODE_NOCALLBACK:
|
||||
case VCHIQ_BULK_MODE_CALLBACK:
|
||||
status = vchiq_bulk_transfer(handle,
|
||||
VCHI_MEM_HANDLE_INVALID, data, size, userdata,
|
||||
mode, VCHIQ_BULK_TRANSMIT);
|
||||
break;
|
||||
case VCHIQ_BULK_MODE_BLOCKING:
|
||||
status = vchiq_blocking_bulk_transfer(handle,
|
||||
data, size, VCHIQ_BULK_TRANSMIT);
|
||||
break;
|
||||
default:
|
||||
return VCHIQ_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_bulk_transmit);
|
||||
|
||||
VCHIQ_STATUS_T
|
||||
vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data,
|
||||
unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode)
|
||||
{
|
||||
VCHIQ_STATUS_T status;
|
||||
|
||||
switch (mode) {
|
||||
case VCHIQ_BULK_MODE_NOCALLBACK:
|
||||
case VCHIQ_BULK_MODE_CALLBACK:
|
||||
status = vchiq_bulk_transfer(handle,
|
||||
VCHI_MEM_HANDLE_INVALID, data, size, userdata,
|
||||
mode, VCHIQ_BULK_RECEIVE);
|
||||
break;
|
||||
case VCHIQ_BULK_MODE_BLOCKING:
|
||||
status = vchiq_blocking_bulk_transfer(handle,
|
||||
data, size, VCHIQ_BULK_RECEIVE);
|
||||
break;
|
||||
default:
|
||||
return VCHIQ_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_bulk_receive);
|
||||
|
||||
static VCHIQ_STATUS_T
|
||||
vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data,
|
||||
unsigned int size, VCHIQ_BULK_DIR_T dir)
|
||||
{
|
||||
VCHIQ_INSTANCE_T instance;
|
||||
VCHIQ_SERVICE_T *service;
|
||||
VCHIQ_STATUS_T status;
|
||||
struct bulk_waiter_node *waiter = NULL;
|
||||
struct list_head *pos;
|
||||
|
||||
service = find_service_by_handle(handle);
|
||||
if (!service)
|
||||
return VCHIQ_ERROR;
|
||||
|
||||
instance = service->instance;
|
||||
|
||||
unlock_service(service);
|
||||
|
||||
lmutex_lock(&instance->bulk_waiter_list_mutex);
|
||||
list_for_each(pos, &instance->bulk_waiter_list) {
|
||||
if (list_entry(pos, struct bulk_waiter_node,
|
||||
list)->pid == current->p_pid) {
|
||||
waiter = list_entry(pos,
|
||||
struct bulk_waiter_node,
|
||||
list);
|
||||
list_del(pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
lmutex_unlock(&instance->bulk_waiter_list_mutex);
|
||||
|
||||
if (waiter) {
|
||||
VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk;
|
||||
if (bulk) {
|
||||
/* This thread has an outstanding bulk transfer. */
|
||||
if ((bulk->data != data) ||
|
||||
(bulk->size != size)) {
|
||||
/* This is not a retry of the previous one.
|
||||
** Cancel the signal when the transfer
|
||||
** completes. */
|
||||
spin_lock(&bulk_waiter_spinlock);
|
||||
bulk->userdata = NULL;
|
||||
spin_unlock(&bulk_waiter_spinlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!waiter) {
|
||||
waiter = kzalloc(sizeof(struct bulk_waiter_node), GFP_KERNEL);
|
||||
if (!waiter) {
|
||||
vchiq_log_error(vchiq_core_log_level,
|
||||
"%s - out of memory", __func__);
|
||||
return VCHIQ_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
status = vchiq_bulk_transfer(handle, VCHI_MEM_HANDLE_INVALID,
|
||||
data, size, &waiter->bulk_waiter, VCHIQ_BULK_MODE_BLOCKING,
|
||||
dir);
|
||||
if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) ||
|
||||
!waiter->bulk_waiter.bulk) {
|
||||
VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk;
|
||||
if (bulk) {
|
||||
/* Cancel the signal when the transfer
|
||||
** completes. */
|
||||
spin_lock(&bulk_waiter_spinlock);
|
||||
bulk->userdata = NULL;
|
||||
spin_unlock(&bulk_waiter_spinlock);
|
||||
}
|
||||
_sema_destroy(&waiter->bulk_waiter.event);
|
||||
|
||||
kfree(waiter);
|
||||
} else {
|
||||
waiter->pid = current->p_pid;
|
||||
lmutex_lock(&instance->bulk_waiter_list_mutex);
|
||||
list_add(&waiter->list, &instance->bulk_waiter_list);
|
||||
lmutex_unlock(&instance->bulk_waiter_list_mutex);
|
||||
vchiq_log_info(vchiq_arm_log_level,
|
||||
"saved bulk_waiter %x for pid %d",
|
||||
(unsigned int)waiter, current->p_pid);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
217
sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c
Normal file
217
sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c
Normal file
@ -0,0 +1,217 @@
|
||||
/*-
|
||||
* Copyright (c) 2012-2015 Oleksandr Tymoshenko <gonzo@freebsd.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/timeet.h>
|
||||
#include <sys/timetc.h>
|
||||
#include <sys/watchdog.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/frame.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/fdt.h>
|
||||
|
||||
#include "vchiq_arm.h"
|
||||
#include "vchiq_2835.h"
|
||||
|
||||
#define VCHIQ_LOCK do { \
|
||||
mtx_lock(&bcm_vchiq_sc->lock); \
|
||||
} while(0)
|
||||
|
||||
#define VCHIQ_UNLOCK do { \
|
||||
mtx_unlock(&bcm_vchiq_sc->lock); \
|
||||
} while(0)
|
||||
|
||||
#ifdef DEBUG
|
||||
#define dprintf(fmt, args...) printf(fmt, ##args)
|
||||
#else
|
||||
#define dprintf(fmt, args...)
|
||||
#endif
|
||||
|
||||
struct bcm_vchiq_softc {
|
||||
struct mtx lock;
|
||||
struct resource * mem_res;
|
||||
struct resource * irq_res;
|
||||
void* intr_hl;
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
};
|
||||
|
||||
static struct bcm_vchiq_softc *bcm_vchiq_sc = NULL;
|
||||
|
||||
#define vchiq_read_4(reg) \
|
||||
bus_space_read_4(bcm_vchiq_sc->bst, bcm_vchiq_sc->bsh, reg)
|
||||
#define vchiq_write_4(reg, val) \
|
||||
bus_space_write_4(bcm_vchiq_sc->bst, bcm_vchiq_sc->bsh, reg, val)
|
||||
|
||||
/*
|
||||
* Extern functions */
|
||||
void vchiq_exit(void);
|
||||
int vchiq_init(void);
|
||||
|
||||
extern VCHIQ_STATE_T g_state;
|
||||
|
||||
static void
|
||||
bcm_vchiq_intr(void *arg)
|
||||
{
|
||||
VCHIQ_STATE_T *state = &g_state;
|
||||
unsigned int status;
|
||||
|
||||
/* Read (and clear) the doorbell */
|
||||
status = vchiq_read_4(0x40);
|
||||
|
||||
if (status & 0x4) { /* Was the doorbell rung? */
|
||||
remote_event_pollall(state);
|
||||
}
|
||||
}
|
||||
|
||||
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 */
|
||||
__asm __volatile ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0) : "memory");
|
||||
vchiq_write_4(0x48, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
bcm_vchiq_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (ofw_bus_is_compatible(dev, "broadcom,bcm2835-vchiq")) {
|
||||
device_set_desc(dev, "BCM2835 VCHIQ");
|
||||
return(BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
bcm_vchiq_attach(device_t dev)
|
||||
{
|
||||
struct bcm_vchiq_softc *sc = device_get_softc(dev);
|
||||
int rid = 0;
|
||||
|
||||
if (bcm_vchiq_sc != NULL)
|
||||
return (EINVAL);
|
||||
|
||||
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
|
||||
if (sc->mem_res == NULL) {
|
||||
device_printf(dev, "could not allocate memory resource\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
sc->bst = rman_get_bustag(sc->mem_res);
|
||||
sc->bsh = rman_get_bushandle(sc->mem_res);
|
||||
|
||||
rid = 0;
|
||||
sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
|
||||
if (sc->irq_res == NULL) {
|
||||
device_printf(dev, "could not allocate interrupt resource\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
vchiq_core_initialize();
|
||||
|
||||
/* Setup and enable the timer */
|
||||
if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC,
|
||||
NULL, bcm_vchiq_intr, sc,
|
||||
&sc->intr_hl) != 0) {
|
||||
bus_release_resource(dev, SYS_RES_IRQ, rid,
|
||||
sc->irq_res);
|
||||
device_printf(dev, "Unable to setup the clock irq handler.\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
mtx_init(&sc->lock, "vchiq", MTX_DEF, 0);
|
||||
bcm_vchiq_sc = sc;
|
||||
|
||||
vchiq_init();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bcm_vchiq_detach(device_t dev)
|
||||
{
|
||||
struct bcm_vchiq_softc *sc = device_get_softc(dev);
|
||||
|
||||
vchiq_exit();
|
||||
|
||||
if (sc->intr_hl)
|
||||
bus_teardown_intr(dev, sc->irq_res, sc->intr_hl);
|
||||
bus_release_resource(dev, SYS_RES_IRQ, 0,
|
||||
sc->irq_res);
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, 0,
|
||||
sc->mem_res);
|
||||
|
||||
mtx_destroy(&sc->lock);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static device_method_t bcm_vchiq_methods[] = {
|
||||
DEVMETHOD(device_probe, bcm_vchiq_probe),
|
||||
DEVMETHOD(device_attach, bcm_vchiq_attach),
|
||||
DEVMETHOD(device_detach, bcm_vchiq_detach),
|
||||
|
||||
/* Bus interface */
|
||||
DEVMETHOD(bus_add_child, bus_generic_add_child),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t bcm_vchiq_driver = {
|
||||
"vchiq",
|
||||
bcm_vchiq_methods,
|
||||
sizeof(struct bcm_vchiq_softc),
|
||||
};
|
||||
|
||||
static devclass_t bcm_vchiq_devclass;
|
||||
|
||||
DRIVER_MODULE(vchiq, simplebus, bcm_vchiq_driver, bcm_vchiq_devclass, 0, 0);
|
||||
MODULE_VERSION(vchiq, 1);
|
71
sys/contrib/vchiq/interface/vchiq_arm/vchiq_memdrv.h
Normal file
71
sys/contrib/vchiq/interface/vchiq_arm/vchiq_memdrv.h
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef 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);
|
||||
|
||||
VCHIQ_STATUS_T vchiq_userdrv_create_instance(
|
||||
const VCHIQ_PLATFORM_DATA_T * platform_data);
|
||||
|
||||
VCHIQ_STATUS_T vchiq_userdrv_suspend(
|
||||
const VCHIQ_PLATFORM_DATA_T * platform_data);
|
||||
|
||||
VCHIQ_STATUS_T vchiq_userdrv_resume(
|
||||
const VCHIQ_PLATFORM_DATA_T * platform_data);
|
||||
|
||||
#endif
|
59
sys/contrib/vchiq/interface/vchiq_arm/vchiq_pagelist.h
Normal file
59
sys/contrib/vchiq/interface/vchiq_arm/vchiq_pagelist.h
Normal file
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef VCHIQ_PAGELIST_H
|
||||
#define VCHIQ_PAGELIST_H
|
||||
|
||||
#ifndef PAGE_SIZE
|
||||
#define PAGE_SIZE 4096
|
||||
#endif
|
||||
#undef CACHE_LINE_SIZE
|
||||
#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 */
|
240
sys/contrib/vchiq/interface/vchiq_arm/vchiq_proc.c
Normal file
240
sys/contrib/vchiq/interface/vchiq_arm/vchiq_proc.c
Normal file
@ -0,0 +1,240 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/proc_fs.h>
|
||||
#include "vchiq_core.h"
|
||||
#include "vchiq_arm.h"
|
||||
|
||||
struct vchiq_proc_info {
|
||||
/* Global 'vc' proc entry used by all instances */
|
||||
struct proc_dir_entry *vc_cfg_dir;
|
||||
|
||||
/* one entry per client process */
|
||||
struct proc_dir_entry *clients;
|
||||
|
||||
/* log categories */
|
||||
struct proc_dir_entry *log_categories;
|
||||
};
|
||||
|
||||
static struct vchiq_proc_info proc_info;
|
||||
|
||||
struct proc_dir_entry *vchiq_proc_top(void)
|
||||
{
|
||||
BUG_ON(proc_info.vc_cfg_dir == NULL);
|
||||
return proc_info.vc_cfg_dir;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* log category entries
|
||||
*
|
||||
***************************************************************************/
|
||||
#define PROC_WRITE_BUF_SIZE 256
|
||||
|
||||
#define VCHIQ_LOG_ERROR_STR "error"
|
||||
#define VCHIQ_LOG_WARNING_STR "warning"
|
||||
#define VCHIQ_LOG_INFO_STR "info"
|
||||
#define VCHIQ_LOG_TRACE_STR "trace"
|
||||
|
||||
static int log_cfg_read(char *buffer,
|
||||
char **start,
|
||||
off_t off,
|
||||
int count,
|
||||
int *eof,
|
||||
void *data)
|
||||
{
|
||||
int len = 0;
|
||||
char *log_value = NULL;
|
||||
|
||||
switch (*((int *)data)) {
|
||||
case VCHIQ_LOG_ERROR:
|
||||
log_value = VCHIQ_LOG_ERROR_STR;
|
||||
break;
|
||||
case VCHIQ_LOG_WARNING:
|
||||
log_value = VCHIQ_LOG_WARNING_STR;
|
||||
break;
|
||||
case VCHIQ_LOG_INFO:
|
||||
log_value = VCHIQ_LOG_INFO_STR;
|
||||
break;
|
||||
case VCHIQ_LOG_TRACE:
|
||||
log_value = VCHIQ_LOG_TRACE_STR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
len += snprintf(buffer + len, count - len,
|
||||
"%s\n",
|
||||
log_value ? log_value : "(null)");
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int log_cfg_write(struct file *file,
|
||||
const char __user *buffer,
|
||||
unsigned long count,
|
||||
void *data)
|
||||
{
|
||||
int *log_module = data;
|
||||
char kbuf[PROC_WRITE_BUF_SIZE + 1];
|
||||
|
||||
(void)file;
|
||||
|
||||
memset(kbuf, 0, PROC_WRITE_BUF_SIZE + 1);
|
||||
if (count >= PROC_WRITE_BUF_SIZE)
|
||||
count = PROC_WRITE_BUF_SIZE;
|
||||
|
||||
if (copy_from_user(kbuf,
|
||||
buffer,
|
||||
count) != 0)
|
||||
return -EFAULT;
|
||||
kbuf[count - 1] = 0;
|
||||
|
||||
if (strncmp("error", kbuf, strlen("error")) == 0)
|
||||
*log_module = VCHIQ_LOG_ERROR;
|
||||
else if (strncmp("warning", kbuf, strlen("warning")) == 0)
|
||||
*log_module = VCHIQ_LOG_WARNING;
|
||||
else if (strncmp("info", kbuf, strlen("info")) == 0)
|
||||
*log_module = VCHIQ_LOG_INFO;
|
||||
else if (strncmp("trace", kbuf, strlen("trace")) == 0)
|
||||
*log_module = VCHIQ_LOG_TRACE;
|
||||
else
|
||||
*log_module = VCHIQ_LOG_DEFAULT;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Log category proc entries */
|
||||
struct vchiq_proc_log_entry {
|
||||
const char *name;
|
||||
int *plevel;
|
||||
struct proc_dir_entry *dir;
|
||||
};
|
||||
|
||||
static struct vchiq_proc_log_entry vchiq_proc_log_entries[] = {
|
||||
{ "core", &vchiq_core_log_level },
|
||||
{ "msg", &vchiq_core_msg_log_level },
|
||||
{ "sync", &vchiq_sync_log_level },
|
||||
{ "susp", &vchiq_susp_log_level },
|
||||
{ "arm", &vchiq_arm_log_level },
|
||||
};
|
||||
static int n_log_entries =
|
||||
sizeof(vchiq_proc_log_entries)/sizeof(vchiq_proc_log_entries[0]);
|
||||
|
||||
/* create an entry under /proc/vc/log for each log category */
|
||||
static int vchiq_proc_create_log_entries(struct proc_dir_entry *top)
|
||||
{
|
||||
struct proc_dir_entry *dir;
|
||||
size_t i;
|
||||
int ret = 0;
|
||||
|
||||
dir = proc_mkdir("log", proc_info.vc_cfg_dir);
|
||||
if (!dir)
|
||||
return -ENOMEM;
|
||||
proc_info.log_categories = dir;
|
||||
|
||||
for (i = 0; i < n_log_entries; i++) {
|
||||
dir = create_proc_entry(vchiq_proc_log_entries[i].name,
|
||||
0644,
|
||||
proc_info.log_categories);
|
||||
if (!dir) {
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
dir->read_proc = &log_cfg_read;
|
||||
dir->write_proc = &log_cfg_write;
|
||||
dir->data = (void *)vchiq_proc_log_entries[i].plevel;
|
||||
|
||||
vchiq_proc_log_entries[i].dir = dir;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int vchiq_proc_init(void)
|
||||
{
|
||||
BUG_ON(proc_info.vc_cfg_dir != NULL);
|
||||
|
||||
proc_info.vc_cfg_dir = proc_mkdir("vc", NULL);
|
||||
if (proc_info.vc_cfg_dir == NULL)
|
||||
goto fail;
|
||||
|
||||
proc_info.clients = proc_mkdir("clients",
|
||||
proc_info.vc_cfg_dir);
|
||||
if (!proc_info.clients)
|
||||
goto fail;
|
||||
|
||||
if (vchiq_proc_create_log_entries(proc_info.vc_cfg_dir) != 0)
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
vchiq_proc_deinit();
|
||||
vchiq_log_error(vchiq_arm_log_level,
|
||||
"%s: failed to create proc directory",
|
||||
__func__);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* remove all the proc entries */
|
||||
void vchiq_proc_deinit(void)
|
||||
{
|
||||
/* log category entries */
|
||||
if (proc_info.log_categories) {
|
||||
size_t i;
|
||||
for (i = 0; i < n_log_entries; i++)
|
||||
if (vchiq_proc_log_entries[i].dir)
|
||||
remove_proc_entry(
|
||||
vchiq_proc_log_entries[i].name,
|
||||
proc_info.log_categories);
|
||||
|
||||
remove_proc_entry(proc_info.log_categories->name,
|
||||
proc_info.vc_cfg_dir);
|
||||
}
|
||||
if (proc_info.clients)
|
||||
remove_proc_entry(proc_info.clients->name,
|
||||
proc_info.vc_cfg_dir);
|
||||
if (proc_info.vc_cfg_dir)
|
||||
remove_proc_entry(proc_info.vc_cfg_dir->name, NULL);
|
||||
}
|
||||
|
||||
struct proc_dir_entry *vchiq_clients_top(void)
|
||||
{
|
||||
return proc_info.clients;
|
||||
}
|
||||
|
830
sys/contrib/vchiq/interface/vchiq_arm/vchiq_shim.c
Normal file
830
sys/contrib/vchiq/interface/vchiq_arm/vchiq_shim.c
Normal file
@ -0,0 +1,830 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <interface/compat/vchi_bsd.h>
|
||||
|
||||
#include "interface/vchi/vchi.h"
|
||||
#include "vchiq.h"
|
||||
#include "vchiq_core.h"
|
||||
|
||||
#include "vchiq_util.h"
|
||||
|
||||
#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
|
||||
* -------------------------------------------------------------------- */
|
||||
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)
|
||||
{
|
||||
(void)function_table;
|
||||
(void)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;
|
||||
|
||||
WARN_ON((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;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_msg_peek);
|
||||
|
||||
/***********************************************************
|
||||
* 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;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_msg_remove);
|
||||
|
||||
/***********************************************************
|
||||
* 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;
|
||||
|
||||
(void)msg_handle;
|
||||
|
||||
WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED);
|
||||
|
||||
status = vchiq_queue_message(service->handle, &element, 1);
|
||||
|
||||
/* vchiq_queue_message() may return VCHIQ_RETRY, so we need to
|
||||
** implement a retry mechanism since this function is supposed
|
||||
** to block until queued
|
||||
*/
|
||||
while (status == VCHIQ_RETRY) {
|
||||
msleep(1);
|
||||
status = vchiq_queue_message(service->handle, &element, 1);
|
||||
}
|
||||
|
||||
return vchiq_status_to_vchi(status);
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_msg_queue);
|
||||
|
||||
/***********************************************************
|
||||
* 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:
|
||||
WARN_ON(!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:
|
||||
WARN(1, "unsupported message\n");
|
||||
return vchiq_status_to_vchi(VCHIQ_ERROR);
|
||||
}
|
||||
|
||||
status = vchiq_bulk_receive(service->handle, data_dst, data_size,
|
||||
bulk_handle, mode);
|
||||
|
||||
/* vchiq_bulk_receive() may return VCHIQ_RETRY, so we need to
|
||||
** implement a retry mechanism since this function is supposed
|
||||
** to block until queued
|
||||
*/
|
||||
while (status == VCHIQ_RETRY) {
|
||||
msleep(1);
|
||||
status = vchiq_bulk_receive(service->handle, data_dst,
|
||||
data_size, bulk_handle, mode);
|
||||
}
|
||||
|
||||
return vchiq_status_to_vchi(status);
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_bulk_queue_receive);
|
||||
|
||||
/***********************************************************
|
||||
* Name: vchi_bulk_queue_transmit
|
||||
*
|
||||
* Arguments: VCHI_BULK_HANDLE_T handle,
|
||||
* 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,
|
||||
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:
|
||||
WARN_ON(!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:
|
||||
WARN(1, "unsupported message\n");
|
||||
return vchiq_status_to_vchi(VCHIQ_ERROR);
|
||||
}
|
||||
|
||||
status = vchiq_bulk_transmit(service->handle, data_src, data_size,
|
||||
bulk_handle, mode);
|
||||
|
||||
/* vchiq_bulk_transmit() may return VCHIQ_RETRY, so we need to
|
||||
** implement a retry mechanism since this function is supposed
|
||||
** to block until queued
|
||||
*/
|
||||
while (status == VCHIQ_RETRY) {
|
||||
msleep(1);
|
||||
status = vchiq_bulk_transmit(service->handle, data_src,
|
||||
data_size, bulk_handle, mode);
|
||||
}
|
||||
|
||||
return vchiq_status_to_vchi(status);
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_bulk_queue_transmit);
|
||||
|
||||
/***********************************************************
|
||||
* 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;
|
||||
|
||||
WARN_ON((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;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_msg_dequeue);
|
||||
|
||||
/***********************************************************
|
||||
* Name: vchi_msg_queuev
|
||||
*
|
||||
* Arguments: VCHI_SERVICE_HANDLE_T handle,
|
||||
* VCHI_MSG_VECTOR_T *vector,
|
||||
* uint32_t count,
|
||||
* VCHI_FLAGS_T flags,
|
||||
* void *msg_handle
|
||||
*
|
||||
* Description: Thin wrapper to queue a message onto a connection
|
||||
*
|
||||
* Returns: int32_t - success == 0
|
||||
*
|
||||
***********************************************************/
|
||||
|
||||
vchiq_static_assert(sizeof(VCHI_MSG_VECTOR_T) == sizeof(VCHIQ_ELEMENT_T));
|
||||
vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_base) ==
|
||||
offsetof(VCHIQ_ELEMENT_T, data));
|
||||
vchiq_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;
|
||||
|
||||
(void)msg_handle;
|
||||
|
||||
WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED);
|
||||
|
||||
return vchiq_status_to_vchi(vchiq_queue_message(service->handle,
|
||||
(const VCHIQ_ELEMENT_T *)vector, count));
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_msg_queuev);
|
||||
|
||||
/***********************************************************
|
||||
* 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;
|
||||
|
||||
WARN_ON((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);
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_initialise);
|
||||
|
||||
/***********************************************************
|
||||
* 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;
|
||||
|
||||
(void)connections;
|
||||
(void)num_connections;
|
||||
|
||||
return vchiq_connect(instance);
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_connect);
|
||||
|
||||
|
||||
/***********************************************************
|
||||
* 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));
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_disconnect);
|
||||
|
||||
|
||||
/***********************************************************
|
||||
* 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);
|
||||
|
||||
if (!service->callback)
|
||||
goto release;
|
||||
|
||||
switch (reason) {
|
||||
case VCHIQ_MESSAGE_AVAILABLE:
|
||||
vchiu_queue_push(&service->queue, header);
|
||||
|
||||
service->callback(service->callback_param,
|
||||
VCHI_CALLBACK_MSG_AVAILABLE, NULL);
|
||||
|
||||
goto done;
|
||||
break;
|
||||
|
||||
case VCHIQ_BULK_TRANSMIT_DONE:
|
||||
service->callback(service->callback_param,
|
||||
VCHI_CALLBACK_BULK_SENT, bulk_user);
|
||||
break;
|
||||
|
||||
case VCHIQ_BULK_RECEIVE_DONE:
|
||||
service->callback(service->callback_param,
|
||||
VCHI_CALLBACK_BULK_RECEIVED, bulk_user);
|
||||
break;
|
||||
|
||||
case VCHIQ_SERVICE_CLOSED:
|
||||
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:
|
||||
service->callback(service->callback_param,
|
||||
VCHI_CALLBACK_BULK_TRANSMIT_ABORTED,
|
||||
bulk_user);
|
||||
break;
|
||||
|
||||
case VCHIQ_BULK_RECEIVE_ABORTED:
|
||||
service->callback(service->callback_param,
|
||||
VCHI_CALLBACK_BULK_RECEIVE_ABORTED,
|
||||
bulk_user);
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN(1, "not supported\n");
|
||||
break;
|
||||
}
|
||||
|
||||
release:
|
||||
vchiq_release_message(service->handle, header);
|
||||
done:
|
||||
return VCHIQ_SUCCESS;
|
||||
}
|
||||
|
||||
static SHIM_SERVICE_T *service_alloc(VCHIQ_INSTANCE_T instance,
|
||||
SERVICE_CREATION_T *setup)
|
||||
{
|
||||
SHIM_SERVICE_T *service = kzalloc(sizeof(SHIM_SERVICE_T), GFP_KERNEL);
|
||||
|
||||
(void)instance;
|
||||
|
||||
if (service) {
|
||||
if (vchiu_queue_init(&service->queue, 64)) {
|
||||
service->callback = setup->callback;
|
||||
service->callback_param = setup->callback_param;
|
||||
} else {
|
||||
kfree(service);
|
||||
service = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
static void service_free(SHIM_SERVICE_T *service)
|
||||
{
|
||||
if (service) {
|
||||
vchiu_queue_delete(&service->queue);
|
||||
kfree(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);
|
||||
|
||||
*handle = (VCHI_SERVICE_HANDLE_T)service;
|
||||
|
||||
if (service) {
|
||||
VCHIQ_SERVICE_PARAMS_T params;
|
||||
VCHIQ_STATUS_T status;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.fourcc = setup->service_id;
|
||||
params.callback = shim_callback;
|
||||
params.userdata = service;
|
||||
params.version = setup->version.version;
|
||||
params.version_min = setup->version.version_min;
|
||||
|
||||
status = vchiq_open_service(instance, ¶ms,
|
||||
&service->handle);
|
||||
if (status != VCHIQ_SUCCESS) {
|
||||
service_free(service);
|
||||
service = NULL;
|
||||
*handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (service != NULL) ? 0 : -1;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_service_open);
|
||||
|
||||
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);
|
||||
|
||||
*handle = (VCHI_SERVICE_HANDLE_T)service;
|
||||
|
||||
if (service) {
|
||||
VCHIQ_SERVICE_PARAMS_T params;
|
||||
VCHIQ_STATUS_T status;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.fourcc = setup->service_id;
|
||||
params.callback = shim_callback;
|
||||
params.userdata = service;
|
||||
params.version = setup->version.version;
|
||||
params.version_min = setup->version.version_min;
|
||||
status = vchiq_add_service(instance, ¶ms, &service->handle);
|
||||
|
||||
if (status != VCHIQ_SUCCESS) {
|
||||
service_free(service);
|
||||
service = NULL;
|
||||
*handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (service != NULL) ? 0 : -1;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_service_create);
|
||||
|
||||
int32_t vchi_service_close(const VCHI_SERVICE_HANDLE_T handle)
|
||||
{
|
||||
int32_t ret = -1;
|
||||
SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
|
||||
if (service) {
|
||||
VCHIQ_STATUS_T status = vchiq_close_service(service->handle);
|
||||
if (status == VCHIQ_SUCCESS) {
|
||||
service_free(service);
|
||||
service = NULL;
|
||||
}
|
||||
|
||||
ret = vchiq_status_to_vchi(status);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_service_close);
|
||||
|
||||
int32_t vchi_service_destroy(const VCHI_SERVICE_HANDLE_T handle)
|
||||
{
|
||||
int32_t ret = -1;
|
||||
SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
|
||||
if (service) {
|
||||
VCHIQ_STATUS_T status = vchiq_remove_service(service->handle);
|
||||
if (status == VCHIQ_SUCCESS) {
|
||||
service_free(service);
|
||||
service = NULL;
|
||||
}
|
||||
|
||||
ret = vchiq_status_to_vchi(status);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_service_destroy);
|
||||
|
||||
int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle, short *peer_version )
|
||||
{
|
||||
int32_t ret = -1;
|
||||
SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
|
||||
if(service)
|
||||
{
|
||||
VCHIQ_STATUS_T status = vchiq_get_peer_version(service->handle, peer_version);
|
||||
ret = vchiq_status_to_vchi( status );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_get_peer_version);
|
||||
|
||||
#ifdef notyet
|
||||
/* ----------------------------------------------------------------------
|
||||
* 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;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***********************************************************
|
||||
* 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;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_service_use);
|
||||
|
||||
/***********************************************************
|
||||
* 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;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_service_release);
|
151
sys/contrib/vchiq/interface/vchiq_arm/vchiq_util.c
Normal file
151
sys/contrib/vchiq/interface/vchiq_arm/vchiq_util.c
Normal file
@ -0,0 +1,151 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "vchiq_util.h"
|
||||
|
||||
static inline int is_pow2(int i)
|
||||
{
|
||||
return i && !(i & (i - 1));
|
||||
}
|
||||
|
||||
int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size)
|
||||
{
|
||||
WARN_ON(!is_pow2(size));
|
||||
|
||||
queue->size = size;
|
||||
queue->read = 0;
|
||||
queue->write = 0;
|
||||
|
||||
_sema_init(&queue->pop, 0);
|
||||
_sema_init(&queue->push, 0);
|
||||
|
||||
queue->storage = kzalloc(size * sizeof(VCHIQ_HEADER_T *), GFP_KERNEL);
|
||||
if (queue->storage == NULL) {
|
||||
vchiu_queue_delete(queue);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void vchiu_queue_delete(VCHIU_QUEUE_T *queue)
|
||||
{
|
||||
if (queue->storage != NULL)
|
||||
kfree(queue->storage);
|
||||
}
|
||||
|
||||
int vchiu_queue_is_empty(VCHIU_QUEUE_T *queue)
|
||||
{
|
||||
return queue->read == queue->write;
|
||||
}
|
||||
|
||||
int vchiu_queue_is_full(VCHIU_QUEUE_T *queue)
|
||||
{
|
||||
return queue->write == queue->read + queue->size;
|
||||
}
|
||||
|
||||
void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header)
|
||||
{
|
||||
while (queue->write == queue->read + queue->size) {
|
||||
if (down_interruptible(&queue->pop) != 0) {
|
||||
flush_signals(current);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to queue->storage must be visible after read from
|
||||
* queue->read
|
||||
*/
|
||||
smp_mb();
|
||||
|
||||
queue->storage[queue->write & (queue->size - 1)] = header;
|
||||
|
||||
/*
|
||||
* Write to queue->storage must be visible before write to
|
||||
* queue->write
|
||||
*/
|
||||
smp_wmb();
|
||||
|
||||
queue->write++;
|
||||
|
||||
up(&queue->push);
|
||||
}
|
||||
|
||||
VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue)
|
||||
{
|
||||
while (queue->write == queue->read) {
|
||||
if (down_interruptible(&queue->push) != 0) {
|
||||
flush_signals(current);
|
||||
}
|
||||
}
|
||||
|
||||
up(&queue->push); // We haven't removed anything from the queue.
|
||||
|
||||
/*
|
||||
* Read from queue->storage must be visible after read from
|
||||
* queue->write
|
||||
*/
|
||||
smp_rmb();
|
||||
|
||||
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) {
|
||||
if (down_interruptible(&queue->push) != 0) {
|
||||
flush_signals(current);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from queue->storage must be visible after read from
|
||||
* queue->write
|
||||
*/
|
||||
smp_rmb();
|
||||
|
||||
header = queue->storage[queue->read & (queue->size - 1)];
|
||||
|
||||
/*
|
||||
* Read from queue->storage must be visible before write to
|
||||
* queue->read
|
||||
*/
|
||||
smp_mb();
|
||||
|
||||
queue->read++;
|
||||
|
||||
up(&queue->pop);
|
||||
|
||||
return header;
|
||||
}
|
66
sys/contrib/vchiq/interface/vchiq_arm/vchiq_util.h
Normal file
66
sys/contrib/vchiq/interface/vchiq_arm/vchiq_util.h
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef VCHIQ_UTIL_H
|
||||
#define VCHIQ_UTIL_H
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <interface/compat/vchi_bsd.h>
|
||||
#endif
|
||||
|
||||
#include "vchiq_if.h"
|
||||
|
||||
typedef struct {
|
||||
int size;
|
||||
int read;
|
||||
int write;
|
||||
|
||||
struct semaphore pop;
|
||||
struct semaphore 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 int vchiu_queue_is_full(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
|
||||
|
59
sys/contrib/vchiq/interface/vchiq_arm/vchiq_version.c
Normal file
59
sys/contrib/vchiq/interface/vchiq_arm/vchiq_version.c
Normal file
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "vchiq_build_info.h"
|
||||
#include <linux/broadcom/vc_debug_sym.h>
|
||||
|
||||
VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_hostname, "dc4-arm-01" );
|
||||
VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_version, "9245b4c35b99b3870e1f7dc598c5692b3c66a6f0 (tainted)" );
|
||||
VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_time, __TIME__ );
|
||||
VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_date, __DATE__ );
|
||||
|
||||
const char *vchiq_get_build_hostname( void )
|
||||
{
|
||||
return vchiq_build_hostname;
|
||||
}
|
||||
|
||||
const char *vchiq_get_build_version( void )
|
||||
{
|
||||
return vchiq_build_version;
|
||||
}
|
||||
|
||||
const char *vchiq_get_build_date( void )
|
||||
{
|
||||
return vchiq_build_date;
|
||||
}
|
||||
|
||||
const char *vchiq_get_build_time( void )
|
||||
{
|
||||
return vchiq_build_time;
|
||||
}
|
Loading…
Reference in New Issue
Block a user