2 * Copyright (c) 2010 Max Khon <fjoe@freebsd.org>
5 * This software was developed by Max Khon under sponsorship from
6 * the FreeBSD Foundation and Ethon Technologies GmbH.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * $Id: bsd-compat.c 9253 2010-09-02 10:12:09Z fjoe $
32 #include <sys/types.h>
33 #include <sys/limits.h>
35 #include <sys/callout.h>
36 #include <sys/firmware.h>
37 #include <sys/param.h>
39 #include <sys/syscallsubr.h>
40 #include <sys/systm.h>
41 #include <sys/taskqueue.h>
43 #include <machine/stdarg.h>
47 #include <interface/compat/vchi_bsd.h>
49 MALLOC_DEFINE(M_VCHI, "VCHI", "VCHI");
57 struct timer_list *t = (struct timer_list *) arg;
58 void (*function)(unsigned long);
60 mtx_lock_spin(&t->mtx);
61 if (callout_pending(&t->callout)) {
62 /* callout was reset */
63 mtx_unlock_spin(&t->mtx);
66 if (!callout_active(&t->callout)) {
67 /* callout was stopped */
68 mtx_unlock_spin(&t->mtx);
71 callout_deactivate(&t->callout);
73 function = t->function;
74 mtx_unlock_spin(&t->mtx);
80 init_timer(struct timer_list *t)
82 mtx_init(&t->mtx, "dahdi timer lock", NULL, MTX_SPIN);
83 callout_init(&t->callout, 1);
86 * function and data are not initialized intentionally:
87 * they are not initialized by Linux implementation too
92 setup_timer(struct timer_list *t, void (*function)(unsigned long), unsigned long data)
94 t->function = function;
100 mod_timer(struct timer_list *t, unsigned long expires)
102 mtx_lock_spin(&t->mtx);
103 callout_reset(&t->callout, expires - jiffies, run_timer, t);
104 mtx_unlock_spin(&t->mtx);
108 add_timer(struct timer_list *t)
110 mod_timer(t, t->expires);
114 del_timer_sync(struct timer_list *t)
116 mtx_lock_spin(&t->mtx);
117 callout_stop(&t->callout);
118 mtx_unlock_spin(&t->mtx);
120 mtx_destroy(&t->mtx);
125 del_timer(struct timer_list *t)
135 init_completion(struct completion *c)
137 cv_init(&c->cv, "VCHI completion cv");
138 mtx_init(&c->lock, "VCHI completion lock", "condvar", MTX_DEF);
143 destroy_completion(struct completion *c)
146 mtx_destroy(&c->lock);
150 complete(struct completion *c)
155 KASSERT(c->done < INT_MAX, ("c->done overflow")); /* XXX check */
159 KASSERT(c->done == -1, ("Invalid value of c->done: %d", c->done));
162 mtx_unlock(&c->lock);
166 complete_all(struct completion *c)
171 KASSERT(c->done < INT_MAX, ("c->done overflow")); /* XXX check */
173 cv_broadcast(&c->cv);
175 KASSERT(c->done == -1, ("Invalid value of c->done: %d", c->done));
178 mtx_unlock(&c->lock);
182 INIT_COMPLETION_locked(struct completion *c)
188 mtx_unlock(&c->lock);
192 _completion_claim(struct completion *c)
195 KASSERT(mtx_owned(&c->lock),
196 ("_completion_claim should be called with acquired lock"));
197 KASSERT(c->done != 0, ("_completion_claim on non-waited completion"));
201 KASSERT(c->done == -1, ("Invalid value of c->done: %d", c->done));
205 wait_for_completion(struct completion *c)
209 cv_wait(&c->cv, &c->lock);
211 mtx_unlock(&c->lock);
215 try_wait_for_completion(struct completion *c)
224 mtx_unlock(&c->lock);
229 wait_for_completion_interruptible_timeout(struct completion *c, unsigned long timeout)
232 unsigned long start, now;
236 while (c->done == 0) {
237 res = cv_timedwait_sig(&c->cv, &c->lock, timeout);
241 if (timeout < (now - start)) {
246 timeout -= (now - start);
250 _completion_claim(c);
254 mtx_unlock(&c->lock);
256 if (res == EWOULDBLOCK) {
258 } else if ((res == EINTR) || (res == ERESTART)) {
261 KASSERT((res == 0), ("res = %d", res));
267 wait_for_completion_interruptible(struct completion *c)
272 while (c->done == 0) {
273 res = cv_wait_sig(&c->cv, &c->lock);
278 _completion_claim(c);
281 mtx_unlock(&c->lock);
283 if ((res == EINTR) || (res == ERESTART))
289 wait_for_completion_killable(struct completion *c)
292 return wait_for_completion_interruptible(c);
299 void sema_sysinit(void *arg)
301 struct semaphore *s = arg;
307 _sema_init(struct semaphore *s, int value)
309 bzero(s, sizeof(*s));
310 mtx_init(&s->mtx, "sema lock", "VCHIQ sepmaphore backing lock",
311 MTX_DEF | MTX_NOWITNESS | MTX_QUIET);
312 cv_init(&s->cv, "sema cv");
317 _sema_destroy(struct semaphore *s)
319 mtx_destroy(&s->mtx);
324 down(struct semaphore *s)
328 while (s->value == 0) {
330 cv_wait(&s->cv, &s->mtx);
339 down_interruptible(struct semaphore *s)
347 while (s->value == 0) {
349 ret = cv_wait_sig(&s->cv, &s->mtx);
368 down_trylock(struct semaphore *s)
390 up(struct semaphore *s)
394 if (s->waiters && s->value > 0)
404 rlprintf(int pps, const char *fmt, ...)
407 static struct timeval last_printf;
410 if (ppsratecheck(&last_printf, &count, pps)) {
418 device_rlprintf(int pps, device_t dev, const char *fmt, ...)
421 static struct timeval last_printf;
424 if (ppsratecheck(&last_printf, &count, pps)) {
426 device_print_prettyname(dev);
437 flush_signals(VCHIQ_THREAD_T thr)
439 printf("Implement ME: %s\n", __func__);
443 fatal_signal_pending(VCHIQ_THREAD_T thr)
445 printf("Implement ME: %s\n", __func__);
454 * This is a hack to avoid memory leak
456 #define MAX_THREAD_DATA_SLOTS 32
457 static int thread_data_slot = 0;
461 int (*threadfn)(void *);
464 static struct thread_data thread_slots[MAX_THREAD_DATA_SLOTS];
467 kthread_wrapper(void *data)
469 struct thread_data *slot;
472 slot->threadfn(slot->data);
476 vchiq_thread_create(int (*threadfn)(void *data),
478 const char namefmt[], ...)
482 char name[MAXCOMLEN+1];
483 struct thread_data *slot;
485 if (thread_data_slot >= MAX_THREAD_DATA_SLOTS) {
486 printf("kthread_create: out of thread data slots\n");
490 slot = &thread_slots[thread_data_slot];
492 slot->threadfn = threadfn;
494 va_start(ap, namefmt);
495 vsnprintf(name, sizeof(name), namefmt, ap);
499 if (kproc_create(kthread_wrapper, (void*)slot, &newp, 0, 0,
501 /* Just to be sure */
511 set_user_nice(VCHIQ_THREAD_T thr, int nice)
517 wake_up_process(VCHIQ_THREAD_T thr)
523 bcm_mbox_write(int channel, uint32_t data)
527 mbox = devclass_get_device(devclass_find("mbox"), 0);
530 MBOX_WRITE(mbox, channel, data);