The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/vchiq/interface/compat/vchi_bsd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2010 Max Khon <fjoe@freebsd.org>
    3  * All rights reserved.
    4  *
    5  * This software was developed by Max Khon under sponsorship from
    6  * the FreeBSD Foundation and Ethon Technologies GmbH.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   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.
   16  *
   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
   27  * SUCH DAMAGE.
   28  *
   29  * $Id: bsd-compat.c 9253 2010-09-02 10:12:09Z fjoe $
   30  */
   31 
   32 #include <sys/types.h>
   33 #include <sys/limits.h>
   34 #include <sys/bus.h>
   35 #include <sys/callout.h>
   36 #include <sys/firmware.h>
   37 #include <sys/param.h>
   38 #include <sys/proc.h>
   39 #include <sys/syscallsubr.h>
   40 #include <sys/systm.h>
   41 #include <sys/taskqueue.h>
   42 
   43 #include <machine/stdarg.h>
   44 
   45 #include "mbox_if.h"
   46 
   47 #include <interface/compat/vchi_bsd.h>
   48 
   49 MALLOC_DEFINE(M_VCHI, "VCHI", "VCHI");
   50 
   51 /*
   52  * Timer API
   53  */
   54 static void
   55 run_timer(void *arg)
   56 {
   57         struct timer_list *t = (struct timer_list *) arg;
   58         void (*function)(unsigned long);
   59 
   60         mtx_lock_spin(&t->mtx);
   61         if (callout_pending(&t->callout)) {
   62                 /* callout was reset */
   63                 mtx_unlock_spin(&t->mtx);
   64                 return;
   65         }
   66         if (!callout_active(&t->callout)) {
   67                 /* callout was stopped */
   68                 mtx_unlock_spin(&t->mtx);
   69                 return;
   70         }
   71         callout_deactivate(&t->callout);
   72 
   73         function = t->function;
   74         mtx_unlock_spin(&t->mtx);
   75 
   76         function(t->data);
   77 }
   78 
   79 void
   80 vchiq_init_timer(struct timer_list *t)
   81 {
   82         mtx_init(&t->mtx, "dahdi timer lock", NULL, MTX_SPIN);
   83         callout_init(&t->callout, 1);
   84         t->expires = 0;
   85         /*
   86          * function and data are not initialized intentionally:
   87          * they are not initialized by Linux implementation too
   88          */
   89 }
   90 
   91 void
   92 vchiq_setup_timer(struct timer_list *t, void (*function)(unsigned long), unsigned long data)
   93 {
   94         t->function = function;
   95         t->data = data;
   96         vchiq_init_timer(t);
   97 }
   98 
   99 void
  100 vchiq_mod_timer(struct timer_list *t, unsigned long expires)
  101 {
  102         mtx_lock_spin(&t->mtx);
  103         callout_reset(&t->callout, expires - jiffies, run_timer, t);
  104         mtx_unlock_spin(&t->mtx);
  105 }
  106 
  107 void
  108 vchiq_add_timer(struct timer_list *t)
  109 {
  110         vchiq_mod_timer(t, t->expires);
  111 }
  112 
  113 int
  114 vchiq_del_timer_sync(struct timer_list *t)
  115 {
  116         mtx_lock_spin(&t->mtx);
  117         callout_stop(&t->callout);
  118         mtx_unlock_spin(&t->mtx);
  119 
  120         mtx_destroy(&t->mtx);
  121         return 0;
  122 }
  123 
  124 int
  125 vchiq_del_timer(struct timer_list *t)
  126 {
  127         vchiq_del_timer_sync(t);
  128         return 0;
  129 }
  130 
  131 /*
  132  * Completion API
  133  */
  134 void
  135 init_completion(struct completion *c)
  136 {
  137         cv_init(&c->cv, "VCHI completion cv");
  138         mtx_init(&c->lock, "VCHI completion lock", "condvar", MTX_DEF);
  139         c->done = 0;
  140 }
  141 
  142 void
  143 destroy_completion(struct completion *c)
  144 {
  145         cv_destroy(&c->cv);
  146         mtx_destroy(&c->lock);
  147 }
  148 
  149 void
  150 complete(struct completion *c)
  151 {
  152         mtx_lock(&c->lock);
  153 
  154         if (c->done >= 0) {
  155                 KASSERT(c->done < INT_MAX, ("c->done overflow")); /* XXX check */
  156                 c->done++;
  157                 cv_signal(&c->cv);
  158         } else {
  159                 KASSERT(c->done == -1, ("Invalid value of c->done: %d", c->done));
  160         }
  161 
  162         mtx_unlock(&c->lock);
  163 }
  164 
  165 void
  166 complete_all(struct completion *c)
  167 {
  168         mtx_lock(&c->lock);
  169 
  170         if (c->done >= 0) {
  171                 KASSERT(c->done < INT_MAX, ("c->done overflow")); /* XXX check */
  172                 c->done = -1;
  173                 cv_broadcast(&c->cv);
  174         } else {
  175                 KASSERT(c->done == -1, ("Invalid value of c->done: %d", c->done));
  176         }
  177 
  178         mtx_unlock(&c->lock);
  179 }
  180 
  181 void
  182 INIT_COMPLETION_locked(struct completion *c)
  183 {
  184         mtx_lock(&c->lock);
  185 
  186         c->done = 0;
  187 
  188         mtx_unlock(&c->lock);
  189 }
  190 
  191 static void
  192 _completion_claim(struct completion *c)
  193 {
  194 
  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"));
  198         if (c->done > 0)
  199                 c->done--;
  200         else
  201                 KASSERT(c->done == -1, ("Invalid value of c->done: %d", c->done));
  202 }
  203 
  204 void
  205 wait_for_completion(struct completion *c)
  206 {
  207         mtx_lock(&c->lock);
  208         if (!c->done)
  209                 cv_wait(&c->cv, &c->lock);
  210         c->done--;
  211         mtx_unlock(&c->lock);
  212 }
  213 
  214 int
  215 try_wait_for_completion(struct completion *c)
  216 {
  217         int res = 0;
  218 
  219         mtx_lock(&c->lock);
  220         if (!c->done)
  221                 res = 1;
  222         else
  223                 c->done--;
  224         mtx_unlock(&c->lock);
  225         return res == 0;
  226 }
  227 
  228 int
  229 wait_for_completion_interruptible_timeout(struct completion *c, unsigned long timeout)
  230 {
  231         int res = 0;
  232         unsigned long start, now;
  233         start = jiffies;
  234 
  235         mtx_lock(&c->lock);
  236         while (c->done == 0) {
  237                 res = cv_timedwait_sig(&c->cv, &c->lock, timeout);
  238                 if (res)
  239                         goto out;
  240                 now = jiffies;
  241                 if (timeout < (now - start)) {
  242                         res = EWOULDBLOCK;
  243                         goto out;
  244                 }
  245 
  246                 timeout -= (now - start);
  247                 start = now;
  248         }
  249 
  250         _completion_claim(c);
  251         res = 0;
  252 
  253 out:
  254         mtx_unlock(&c->lock);
  255 
  256         if (res == EWOULDBLOCK) {
  257                 return 0;
  258         } else if ((res == EINTR) || (res == ERESTART)) {
  259                 return -ERESTART;
  260         } else {
  261                 KASSERT((res == 0), ("res = %d", res));
  262                 return timeout;
  263         }
  264 }
  265 
  266 int
  267 wait_for_completion_interruptible(struct completion *c)
  268 {
  269         int res = 0;
  270 
  271         mtx_lock(&c->lock);
  272         while (c->done == 0) {
  273                 res = cv_wait_sig(&c->cv, &c->lock);
  274                 if (res)
  275                         goto out;
  276         }
  277 
  278         _completion_claim(c);
  279 
  280 out:
  281         mtx_unlock(&c->lock);
  282 
  283         if ((res == EINTR) || (res == ERESTART))
  284                 res = -ERESTART;
  285         return res;
  286 }
  287 
  288 int
  289 wait_for_completion_killable(struct completion *c)
  290 {
  291 
  292         return wait_for_completion_interruptible(c);
  293 }
  294 
  295 /*
  296  * Semaphore API
  297  */
  298 
  299 void sema_sysinit(void *arg)
  300 {
  301         struct semaphore *s = arg;
  302 
  303         _sema_init(s, 1);
  304 }
  305 
  306 void
  307 _sema_init(struct semaphore *s, int value)
  308 {
  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");
  313         s->value = value;
  314 }
  315 
  316 void
  317 _sema_destroy(struct semaphore *s)
  318 {
  319         mtx_destroy(&s->mtx);
  320         cv_destroy(&s->cv);
  321 }
  322 
  323 void
  324 down(struct semaphore *s)
  325 {
  326 
  327         mtx_lock(&s->mtx);
  328         while (s->value == 0) {
  329                 s->waiters++;
  330                 cv_wait(&s->cv, &s->mtx);
  331                 s->waiters--;
  332         }
  333 
  334         s->value--;
  335         mtx_unlock(&s->mtx);
  336 }
  337 
  338 int
  339 down_interruptible(struct semaphore *s)
  340 {
  341         int ret ;
  342 
  343         ret = 0;
  344 
  345         mtx_lock(&s->mtx);
  346 
  347         while (s->value == 0) {
  348                 s->waiters++;
  349                 ret = cv_wait_sig(&s->cv, &s->mtx);
  350                 s->waiters--;
  351 
  352                 if (ret == EINTR) {
  353                         mtx_unlock(&s->mtx);
  354                         return (-EINTR);
  355                 }
  356 
  357                 if (ret == ERESTART)
  358                         continue;
  359         }
  360 
  361         s->value--;
  362         mtx_unlock(&s->mtx);
  363 
  364         return (0);
  365 }
  366 
  367 int
  368 down_trylock(struct semaphore *s)
  369 {
  370         int ret;
  371 
  372         ret = 0;
  373 
  374         mtx_lock(&s->mtx);
  375 
  376         if (s->value > 0) {
  377                 /* Success. */
  378                 s->value--;
  379                 ret = 0;
  380         } else {
  381                 ret = -EAGAIN;
  382         }
  383 
  384         mtx_unlock(&s->mtx);
  385 
  386         return (ret);
  387 }
  388 
  389 void
  390 up(struct semaphore *s)
  391 {
  392         mtx_lock(&s->mtx);
  393         s->value++;
  394         if (s->waiters && s->value > 0)
  395                 cv_signal(&s->cv);
  396 
  397         mtx_unlock(&s->mtx);
  398 }
  399 
  400 /*
  401  * Logging API
  402  */
  403 void
  404 rlprintf(int pps, const char *fmt, ...)
  405 {
  406         va_list ap;
  407         static struct timeval last_printf;
  408         static int count;
  409 
  410         if (ppsratecheck(&last_printf, &count, pps)) {
  411                 va_start(ap, fmt);
  412                 vprintf(fmt, ap);
  413                 va_end(ap);
  414         }
  415 }
  416 
  417 void
  418 device_rlprintf(int pps, device_t dev, const char *fmt, ...)
  419 {
  420         va_list ap;
  421         static struct timeval last_printf;
  422         static int count;
  423 
  424         if (ppsratecheck(&last_printf, &count, pps)) {
  425                 va_start(ap, fmt);
  426                 device_print_prettyname(dev);
  427                 vprintf(fmt, ap);
  428                 va_end(ap);
  429         }
  430 }
  431 
  432 /*
  433  * Signals API
  434  */
  435 
  436 void
  437 flush_signals(VCHIQ_THREAD_T thr)
  438 {
  439         printf("Implement ME: %s\n", __func__);
  440 }
  441 
  442 int
  443 fatal_signal_pending(VCHIQ_THREAD_T thr)
  444 {
  445         printf("Implement ME: %s\n", __func__);
  446         return (0);
  447 }
  448 
  449 /*
  450  * kthread API
  451  */
  452 
  453 /*
  454  *  This is a hack to avoid memory leak
  455  */
  456 #define MAX_THREAD_DATA_SLOTS   32
  457 static int thread_data_slot = 0;
  458 
  459 struct thread_data {
  460         void *data;
  461         int (*threadfn)(void *);
  462 };
  463 
  464 static struct thread_data thread_slots[MAX_THREAD_DATA_SLOTS];
  465 
  466 static void
  467 kthread_wrapper(void *data)
  468 {
  469         struct thread_data *slot;
  470 
  471         slot = data;
  472         slot->threadfn(slot->data);
  473 }
  474 
  475 VCHIQ_THREAD_T
  476 vchiq_thread_create(int (*threadfn)(void *data),
  477         void *data,
  478         const char namefmt[], ...)
  479 {
  480         VCHIQ_THREAD_T newp;
  481         va_list ap;
  482         char name[MAXCOMLEN+1];
  483         struct thread_data *slot;
  484 
  485         if (thread_data_slot >= MAX_THREAD_DATA_SLOTS) {
  486                 printf("kthread_create: out of thread data slots\n");
  487                 return (NULL);
  488         }
  489 
  490         slot = &thread_slots[thread_data_slot];
  491         slot->data = data;
  492         slot->threadfn = threadfn;
  493 
  494         va_start(ap, namefmt);
  495         vsnprintf(name, sizeof(name), namefmt, ap);
  496         va_end(ap);
  497         
  498         newp = NULL;
  499         if (kproc_create(kthread_wrapper, (void*)slot, &newp, 0, 0,
  500             "%s", name) != 0) {
  501                 /* Just to be sure */
  502                 newp = NULL;
  503         }
  504         else
  505                 thread_data_slot++;
  506 
  507         return newp;
  508 }
  509 
  510 void
  511 set_user_nice(VCHIQ_THREAD_T thr, int nice)
  512 {
  513         /* NOOP */
  514 }
  515 
  516 void
  517 wake_up_process(VCHIQ_THREAD_T thr)
  518 {
  519         /* NOOP */
  520 }
  521 
  522 void
  523 bcm_mbox_write(int channel, uint32_t data)
  524 {
  525         device_t mbox;
  526 
  527         mbox = devclass_get_device(devclass_find("mbox"), 0);
  528 
  529         if (mbox)
  530                 MBOX_WRITE(mbox, channel, data);
  531 }

Cache object: 419f5840bca0fbed6c41c85d5f2ef8e0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.