xref: /netbsd-src/sys/external/bsd/vchiq/dist/interface/compat/vchi_bsd.c (revision 5fcdcb153fdb981c27df3115bf293dc0ede1aeec)
1d0c4f7d9Sjmcneill /*-
2d0c4f7d9Sjmcneill  * Copyright (c) 2010 Max Khon <fjoe@freebsd.org>
3d0c4f7d9Sjmcneill  * All rights reserved.
4d0c4f7d9Sjmcneill  *
5d0c4f7d9Sjmcneill  * This software was developed by Max Khon under sponsorship from
6d0c4f7d9Sjmcneill  * the FreeBSD Foundation and Ethon Technologies GmbH.
7d0c4f7d9Sjmcneill  *
8d0c4f7d9Sjmcneill  * Redistribution and use in source and binary forms, with or without
9d0c4f7d9Sjmcneill  * modification, are permitted provided that the following conditions
10d0c4f7d9Sjmcneill  * are met:
11d0c4f7d9Sjmcneill  * 1. Redistributions of source code must retain the above copyright
12d0c4f7d9Sjmcneill  *    notice, this list of conditions and the following disclaimer.
13d0c4f7d9Sjmcneill  * 2. Redistributions in binary form must reproduce the above copyright
14d0c4f7d9Sjmcneill  *    notice, this list of conditions and the following disclaimer in the
15d0c4f7d9Sjmcneill  *    documentation and/or other materials provided with the distribution.
16d0c4f7d9Sjmcneill  *
17d0c4f7d9Sjmcneill  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18d0c4f7d9Sjmcneill  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19d0c4f7d9Sjmcneill  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20d0c4f7d9Sjmcneill  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21d0c4f7d9Sjmcneill  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22d0c4f7d9Sjmcneill  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23d0c4f7d9Sjmcneill  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24d0c4f7d9Sjmcneill  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25d0c4f7d9Sjmcneill  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26d0c4f7d9Sjmcneill  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27d0c4f7d9Sjmcneill  * SUCH DAMAGE.
28d0c4f7d9Sjmcneill  *
29*5fcdcb15Sskrll  * $Id: vchi_bsd.c,v 1.10 2017/11/05 09:11:43 skrll Exp $
30d0c4f7d9Sjmcneill  */
31d0c4f7d9Sjmcneill 
32d0c4f7d9Sjmcneill #include <sys/types.h>
33d0c4f7d9Sjmcneill #include <sys/bus.h>
34d0c4f7d9Sjmcneill #include <sys/callout.h>
35d0c4f7d9Sjmcneill #include <sys/param.h>
36d0c4f7d9Sjmcneill #include <sys/proc.h>
37d0c4f7d9Sjmcneill #include <sys/systm.h>
38d0c4f7d9Sjmcneill 
39d0c4f7d9Sjmcneill #include <interface/compat/vchi_bsd.h>
40d0c4f7d9Sjmcneill 
41d0c4f7d9Sjmcneill MALLOC_DEFINE(M_VCHI, "VCHI", "VCHI");
42d0c4f7d9Sjmcneill 
43d0c4f7d9Sjmcneill /*
44d0c4f7d9Sjmcneill  * Timer API
45d0c4f7d9Sjmcneill  */
46d0c4f7d9Sjmcneill static void
run_timer(void * arg)47d0c4f7d9Sjmcneill run_timer(void *arg)
48d0c4f7d9Sjmcneill {
49d0c4f7d9Sjmcneill 	struct timer_list *t = (struct timer_list *) arg;
50d0c4f7d9Sjmcneill 	void (*function)(unsigned long);
51d0c4f7d9Sjmcneill 
52d0c4f7d9Sjmcneill 	spin_lock(&t->mtx);
53d0c4f7d9Sjmcneill 	if (callout_pending(&t->callout)) {
54d0c4f7d9Sjmcneill 		/* callout was reset */
55d0c4f7d9Sjmcneill 		spin_unlock(&t->mtx);
56d0c4f7d9Sjmcneill 		return;
57d0c4f7d9Sjmcneill 	}
58d0c4f7d9Sjmcneill 	if (!callout_active(&t->callout)) {
59d0c4f7d9Sjmcneill 		/* callout was stopped */
60d0c4f7d9Sjmcneill 		spin_unlock(&t->mtx);
61d0c4f7d9Sjmcneill 		return;
62d0c4f7d9Sjmcneill 	}
63d0c4f7d9Sjmcneill 	callout_ack(&t->callout);
64d0c4f7d9Sjmcneill 
65d0c4f7d9Sjmcneill 	function = t->function;
66d0c4f7d9Sjmcneill 	spin_unlock(&t->mtx);
67d0c4f7d9Sjmcneill 
68d0c4f7d9Sjmcneill 	function(t->data);
69d0c4f7d9Sjmcneill }
70d0c4f7d9Sjmcneill 
71d0c4f7d9Sjmcneill void
init_timer(struct timer_list * t)72d0c4f7d9Sjmcneill init_timer(struct timer_list *t)
73d0c4f7d9Sjmcneill {
74d0c4f7d9Sjmcneill 	spin_lock_init(&t->mtx);
75d0c4f7d9Sjmcneill 	callout_init(&t->callout, CALLOUT_MPSAFE);
76d0c4f7d9Sjmcneill 	t->expires = 0;
77d0c4f7d9Sjmcneill 	/*
78d0c4f7d9Sjmcneill 	 * function and data are not initialized intentionally:
79d0c4f7d9Sjmcneill 	 * they are not initialized by Linux implementation too
80d0c4f7d9Sjmcneill 	 */
81d0c4f7d9Sjmcneill }
82d0c4f7d9Sjmcneill 
83d0c4f7d9Sjmcneill void
setup_timer(struct timer_list * t,void (* function)(unsigned long),unsigned long data)84d0c4f7d9Sjmcneill setup_timer(struct timer_list *t, void (*function)(unsigned long), unsigned long data)
85d0c4f7d9Sjmcneill {
86d0c4f7d9Sjmcneill 	t->function = function;
87d0c4f7d9Sjmcneill 	t->data = data;
88d0c4f7d9Sjmcneill 	init_timer(t);
89d0c4f7d9Sjmcneill }
90d0c4f7d9Sjmcneill 
91d0c4f7d9Sjmcneill void
mod_timer(struct timer_list * t,unsigned long expires)92d0c4f7d9Sjmcneill mod_timer(struct timer_list *t, unsigned long expires)
93d0c4f7d9Sjmcneill {
94d0c4f7d9Sjmcneill 	spin_lock(&t->mtx);
95d0c4f7d9Sjmcneill 	callout_reset(&t->callout, expires - jiffies, run_timer, t);
96d0c4f7d9Sjmcneill 	spin_unlock(&t->mtx);
97d0c4f7d9Sjmcneill }
98d0c4f7d9Sjmcneill 
99d0c4f7d9Sjmcneill void
add_timer(struct timer_list * t)100d0c4f7d9Sjmcneill add_timer(struct timer_list *t)
101d0c4f7d9Sjmcneill {
102d0c4f7d9Sjmcneill 	mod_timer(t, t->expires);
103d0c4f7d9Sjmcneill }
104d0c4f7d9Sjmcneill 
105d0c4f7d9Sjmcneill int
del_timer_sync(struct timer_list * t)106d0c4f7d9Sjmcneill del_timer_sync(struct timer_list *t)
107d0c4f7d9Sjmcneill {
108d0c4f7d9Sjmcneill 	spin_lock(&t->mtx);
10995c59df5Sjmcneill 	callout_halt(&t->callout, &t->mtx);
110d0c4f7d9Sjmcneill 	spin_unlock(&t->mtx);
111d0c4f7d9Sjmcneill 
112d0c4f7d9Sjmcneill 	spin_lock_destroy(&t->mtx);
113d0c4f7d9Sjmcneill 	return 0;
114d0c4f7d9Sjmcneill }
115d0c4f7d9Sjmcneill 
116d0c4f7d9Sjmcneill int
del_timer(struct timer_list * t)117d0c4f7d9Sjmcneill del_timer(struct timer_list *t)
118d0c4f7d9Sjmcneill {
119d0c4f7d9Sjmcneill 	del_timer_sync(t);
120d0c4f7d9Sjmcneill 	return 0;
121d0c4f7d9Sjmcneill }
122d0c4f7d9Sjmcneill 
123d0c4f7d9Sjmcneill /*
124d0c4f7d9Sjmcneill  * Semaphore API
125d0c4f7d9Sjmcneill  */
126d0c4f7d9Sjmcneill 
sema_sysinit(void * arg)127d0c4f7d9Sjmcneill void sema_sysinit(void *arg)
128d0c4f7d9Sjmcneill {
129d0c4f7d9Sjmcneill 	struct semaphore *s = arg;
130d0c4f7d9Sjmcneill 
131d0c4f7d9Sjmcneill 	printf("sema_sysinit\n");
132d0c4f7d9Sjmcneill 	_sema_init(s, 1);
133d0c4f7d9Sjmcneill }
134d0c4f7d9Sjmcneill 
135d0c4f7d9Sjmcneill void
_sema_init(struct semaphore * s,int value)136d0c4f7d9Sjmcneill _sema_init(struct semaphore *s, int value)
137d0c4f7d9Sjmcneill {
138fe334a74Sskrll 	memset(s, 0, sizeof(*s));
139*5fcdcb15Sskrll 	mutex_init(&s->mtx, MUTEX_DEFAULT, IPL_VM);
140d0c4f7d9Sjmcneill 	cv_init(&s->cv, "semacv");
141d0c4f7d9Sjmcneill 	s->value = value;
142d0c4f7d9Sjmcneill }
143d0c4f7d9Sjmcneill 
144d0c4f7d9Sjmcneill void
_sema_destroy(struct semaphore * s)145d0c4f7d9Sjmcneill _sema_destroy(struct semaphore *s)
146d0c4f7d9Sjmcneill {
147d0c4f7d9Sjmcneill 	mutex_destroy(&s->mtx);
148d0c4f7d9Sjmcneill 	cv_destroy(&s->cv);
149d0c4f7d9Sjmcneill }
150d0c4f7d9Sjmcneill 
151d0c4f7d9Sjmcneill void
down(struct semaphore * s)152d0c4f7d9Sjmcneill down(struct semaphore *s)
153d0c4f7d9Sjmcneill {
154d0c4f7d9Sjmcneill 
155d0c4f7d9Sjmcneill 	mutex_enter(&s->mtx);
156d0c4f7d9Sjmcneill 	while (s->value == 0) {
157d0c4f7d9Sjmcneill 		s->waiters++;
158d0c4f7d9Sjmcneill 		cv_wait(&s->cv, &s->mtx);
159d0c4f7d9Sjmcneill 		s->waiters--;
160d0c4f7d9Sjmcneill 	}
161d0c4f7d9Sjmcneill 
162d0c4f7d9Sjmcneill 	s->value--;
163d0c4f7d9Sjmcneill 	mutex_exit(&s->mtx);
164d0c4f7d9Sjmcneill }
165d0c4f7d9Sjmcneill 
166d0c4f7d9Sjmcneill int
down_interruptible(struct semaphore * s)167d0c4f7d9Sjmcneill down_interruptible(struct semaphore *s)
168d0c4f7d9Sjmcneill {
169d0c4f7d9Sjmcneill 
170d0c4f7d9Sjmcneill 	mutex_enter(&s->mtx);
171d0c4f7d9Sjmcneill 
172d0c4f7d9Sjmcneill 	while (s->value == 0) {
173d0c4f7d9Sjmcneill 		s->waiters++;
174d0eeb335Sskrll 		int ret = cv_wait_sig(&s->cv, &s->mtx);
175d0c4f7d9Sjmcneill 		s->waiters--;
176d0c4f7d9Sjmcneill 
177d0c4f7d9Sjmcneill 		if (ret == EINTR || ret == ERESTART) {
178d0c4f7d9Sjmcneill 			mutex_exit(&s->mtx);
179f714ddc6Sskrll 			return -EINTR;
180d0c4f7d9Sjmcneill 		}
181d0c4f7d9Sjmcneill 	}
182d0c4f7d9Sjmcneill 
183d0c4f7d9Sjmcneill 	s->value--;
184d0c4f7d9Sjmcneill 	mutex_exit(&s->mtx);
185d0c4f7d9Sjmcneill 
186f714ddc6Sskrll 	return 0;
187d0c4f7d9Sjmcneill }
188d0c4f7d9Sjmcneill 
189d0c4f7d9Sjmcneill int
down_trylock(struct semaphore * s)190d0c4f7d9Sjmcneill down_trylock(struct semaphore *s)
191d0c4f7d9Sjmcneill {
192d0eeb335Sskrll 	int ret = 1;
193d0c4f7d9Sjmcneill 
194d0c4f7d9Sjmcneill 	mutex_enter(&s->mtx);
195d0c4f7d9Sjmcneill 
196d0c4f7d9Sjmcneill 	if (s->value > 0) {
197d0c4f7d9Sjmcneill 		/* Success. */
198d0c4f7d9Sjmcneill 		s->value--;
199d0c4f7d9Sjmcneill 		ret = 0;
200d0c4f7d9Sjmcneill 	}
201d0c4f7d9Sjmcneill 
202d0c4f7d9Sjmcneill 	mutex_exit(&s->mtx);
203d0c4f7d9Sjmcneill 
204f714ddc6Sskrll 	return ret;
205d0c4f7d9Sjmcneill }
206d0c4f7d9Sjmcneill 
207d0c4f7d9Sjmcneill void
up(struct semaphore * s)208d0c4f7d9Sjmcneill up(struct semaphore *s)
209d0c4f7d9Sjmcneill {
210d0c4f7d9Sjmcneill 	mutex_enter(&s->mtx);
211d0c4f7d9Sjmcneill 	s->value++;
212d0eeb335Sskrll 	if (s->value > 0 && s->waiters)
213d0c4f7d9Sjmcneill 		cv_signal(&s->cv);
214d0c4f7d9Sjmcneill 
215d0c4f7d9Sjmcneill 	mutex_exit(&s->mtx);
216d0c4f7d9Sjmcneill }
217d0c4f7d9Sjmcneill 
218d0c4f7d9Sjmcneill /*
219d0c4f7d9Sjmcneill  * Logging API
220d0c4f7d9Sjmcneill  */
221d0c4f7d9Sjmcneill void
rlprintf(int pps,const char * fmt,...)222d0c4f7d9Sjmcneill rlprintf(int pps, const char *fmt, ...)
223d0c4f7d9Sjmcneill {
224d0c4f7d9Sjmcneill 	va_list ap;
225d0c4f7d9Sjmcneill 	static struct timeval last_printf;
226d0c4f7d9Sjmcneill 	static int count;
227d0c4f7d9Sjmcneill 
228d0c4f7d9Sjmcneill 	if (ppsratecheck(&last_printf, &count, pps)) {
229d0c4f7d9Sjmcneill 		va_start(ap, fmt);
230d0c4f7d9Sjmcneill 		vprintf(fmt, ap);
231d0c4f7d9Sjmcneill 		va_end(ap);
232d0c4f7d9Sjmcneill 	}
233d0c4f7d9Sjmcneill }
234d0c4f7d9Sjmcneill 
235d0c4f7d9Sjmcneill void
device_rlprintf(int pps,device_t dev,const char * fmt,...)236d0c4f7d9Sjmcneill device_rlprintf(int pps, device_t dev, const char *fmt, ...)
237d0c4f7d9Sjmcneill {
238d0c4f7d9Sjmcneill 	va_list ap;
239d0c4f7d9Sjmcneill 	static struct timeval last_printf;
240d0c4f7d9Sjmcneill 	static int count;
241d0c4f7d9Sjmcneill 
242d0c4f7d9Sjmcneill 	if (ppsratecheck(&last_printf, &count, pps)) {
243d0c4f7d9Sjmcneill 		va_start(ap, fmt);
244d0c4f7d9Sjmcneill 		device_print_prettyname(dev);
245d0c4f7d9Sjmcneill 		vprintf(fmt, ap);
246d0c4f7d9Sjmcneill 		va_end(ap);
247d0c4f7d9Sjmcneill 	}
248d0c4f7d9Sjmcneill }
249d0c4f7d9Sjmcneill 
250d0c4f7d9Sjmcneill /*
251d0c4f7d9Sjmcneill  * Signals API
252d0c4f7d9Sjmcneill  */
253d0c4f7d9Sjmcneill 
254d0c4f7d9Sjmcneill void
flush_signals(VCHIQ_THREAD_T thr)255d0c4f7d9Sjmcneill flush_signals(VCHIQ_THREAD_T thr)
256d0c4f7d9Sjmcneill {
257d0c4f7d9Sjmcneill 	printf("Implement ME: %s\n", __func__);
258d0c4f7d9Sjmcneill }
259d0c4f7d9Sjmcneill 
260d0c4f7d9Sjmcneill int
fatal_signal_pending(VCHIQ_THREAD_T thr)261d0c4f7d9Sjmcneill fatal_signal_pending(VCHIQ_THREAD_T thr)
262d0c4f7d9Sjmcneill {
263d0c4f7d9Sjmcneill 	printf("Implement ME: %s\n", __func__);
264f714ddc6Sskrll 	return 0;
265d0c4f7d9Sjmcneill }
266d0c4f7d9Sjmcneill 
267d0c4f7d9Sjmcneill /*
268d0c4f7d9Sjmcneill  * kthread API
269d0c4f7d9Sjmcneill  */
270d0c4f7d9Sjmcneill 
271d0c4f7d9Sjmcneill /*
272d0c4f7d9Sjmcneill  *  This is a hack to avoid memory leak
273d0c4f7d9Sjmcneill  */
274d0c4f7d9Sjmcneill #define MAX_THREAD_DATA_SLOTS	32
275d0c4f7d9Sjmcneill static int thread_data_slot = 0;
276d0c4f7d9Sjmcneill 
277d0c4f7d9Sjmcneill struct thread_data {
278d0c4f7d9Sjmcneill 	void *data;
279d0c4f7d9Sjmcneill 	int (*threadfn)(void *);
280d0c4f7d9Sjmcneill };
281d0c4f7d9Sjmcneill 
282d0c4f7d9Sjmcneill static struct thread_data thread_slots[MAX_THREAD_DATA_SLOTS];
283d0c4f7d9Sjmcneill 
284d0c4f7d9Sjmcneill static void
kthread_wrapper(void * data)285d0c4f7d9Sjmcneill kthread_wrapper(void *data)
286d0c4f7d9Sjmcneill {
287d0c4f7d9Sjmcneill 	struct thread_data *slot;
288d0c4f7d9Sjmcneill 
289d0c4f7d9Sjmcneill 	slot = data;
290d0c4f7d9Sjmcneill 	slot->threadfn(slot->data);
291d0c4f7d9Sjmcneill }
292d0c4f7d9Sjmcneill 
293d0c4f7d9Sjmcneill VCHIQ_THREAD_T
vchiq_thread_create(int (* threadfn)(void * data),void * data,const char namefmt[],...)294d0c4f7d9Sjmcneill vchiq_thread_create(int (*threadfn)(void *data),
295d0c4f7d9Sjmcneill 	void *data,
296d0c4f7d9Sjmcneill 	const char namefmt[], ...)
297d0c4f7d9Sjmcneill {
298d0c4f7d9Sjmcneill 	VCHIQ_THREAD_T newt;
299d0c4f7d9Sjmcneill 	va_list ap;
300d0c4f7d9Sjmcneill 	char name[MAXCOMLEN+1];
301d0c4f7d9Sjmcneill 	struct thread_data *slot;
302d0c4f7d9Sjmcneill 
303d0c4f7d9Sjmcneill 	if (thread_data_slot >= MAX_THREAD_DATA_SLOTS) {
304d0c4f7d9Sjmcneill 		printf("kthread_create: out of thread data slots\n");
305f714ddc6Sskrll 		return NULL;
306d0c4f7d9Sjmcneill 	}
307d0c4f7d9Sjmcneill 
308d0c4f7d9Sjmcneill 	slot = &thread_slots[thread_data_slot];
309d0c4f7d9Sjmcneill 	slot->data = data;
310d0c4f7d9Sjmcneill 	slot->threadfn = threadfn;
311d0c4f7d9Sjmcneill 
312d0c4f7d9Sjmcneill 	va_start(ap, namefmt);
313d0c4f7d9Sjmcneill 	vsnprintf(name, sizeof(name), namefmt, ap);
314d0c4f7d9Sjmcneill 	va_end(ap);
315d0c4f7d9Sjmcneill 
316d0c4f7d9Sjmcneill 	newt = NULL;
31795c59df5Sjmcneill 	if (kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, kthread_wrapper,
31895c59df5Sjmcneill 	    slot, &newt, "%s", name) != 0) {
319d0c4f7d9Sjmcneill 		/* Just to be sure */
320d0c4f7d9Sjmcneill 		newt = NULL;
321d0c4f7d9Sjmcneill 	} else {
322d0c4f7d9Sjmcneill 		thread_data_slot++;
323d0c4f7d9Sjmcneill 	}
324d0c4f7d9Sjmcneill 
325d0c4f7d9Sjmcneill 	return newt;
326d0c4f7d9Sjmcneill }
327d0c4f7d9Sjmcneill 
328d0c4f7d9Sjmcneill void
set_user_nice(VCHIQ_THREAD_T thr,int nice)329d0c4f7d9Sjmcneill set_user_nice(VCHIQ_THREAD_T thr, int nice)
330d0c4f7d9Sjmcneill {
331d0c4f7d9Sjmcneill 	/* NOOP */
332d0c4f7d9Sjmcneill }
333d0c4f7d9Sjmcneill 
334d0c4f7d9Sjmcneill void
wake_up_process(VCHIQ_THREAD_T thr)335d0c4f7d9Sjmcneill wake_up_process(VCHIQ_THREAD_T thr)
336d0c4f7d9Sjmcneill {
337d0c4f7d9Sjmcneill 	/* NOOP */
338d0c4f7d9Sjmcneill }
339