1#ifndef _M68K_SEMAPHORE_H
2#define _M68K_SEMAPHORE_H
3
4#define RW_LOCK_BIAS		 0x01000000
5
6#ifndef __ASSEMBLY__
7
8#include <linux/linkage.h>
9#include <linux/wait.h>
10#include <linux/spinlock.h>
11#include <linux/rwsem.h>
12#include <linux/stringify.h>
13
14#include <asm/system.h>
15#include <asm/atomic.h>
16
17/*
18 * Interrupt-safe semaphores..
19 *
20 * (C) Copyright 1996 Linus Torvalds
21 *
22 * m68k version by Andreas Schwab
23 */
24
25
26struct semaphore {
27	atomic_t count;
28	atomic_t waking;
29	wait_queue_head_t wait;
30};
31
32#define __SEMAPHORE_INITIALIZER(name, n)				\
33{									\
34	.count		= ATOMIC_INIT(n),				\
35	.waking		= ATOMIC_INIT(0),				\
36	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
37}
38
39#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
40	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
41
42#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
43#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
44
45static inline void sema_init(struct semaphore *sem, int val)
46{
47	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER(*sem, val);
48}
49
50static inline void init_MUTEX (struct semaphore *sem)
51{
52	sema_init(sem, 1);
53}
54
55static inline void init_MUTEX_LOCKED (struct semaphore *sem)
56{
57	sema_init(sem, 0);
58}
59
60asmlinkage void __down_failed(void /* special register calling convention */);
61asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
62asmlinkage int  __down_failed_trylock(void  /* params in registers */);
63asmlinkage void __up_wakeup(void /* special register calling convention */);
64
65asmlinkage void __down(struct semaphore * sem);
66asmlinkage int  __down_interruptible(struct semaphore * sem);
67asmlinkage int  __down_trylock(struct semaphore * sem);
68asmlinkage void __up(struct semaphore * sem);
69
70/*
71 * This is ugly, but we want the default case to fall through.
72 * "down_failed" is a special asm handler that calls the C
73 * routine that actually waits. See arch/m68k/lib/semaphore.S
74 */
75static inline void down(struct semaphore *sem)
76{
77	register struct semaphore *sem1 __asm__ ("%a1") = sem;
78
79	might_sleep();
80	__asm__ __volatile__(
81		"| atomic down operation\n\t"
82		"subql #1,%0@\n\t"
83		"jmi 2f\n\t"
84		"1:\n"
85		LOCK_SECTION_START(".even\n\t")
86		"2:\tpea 1b\n\t"
87		"jbra __down_failed\n"
88		LOCK_SECTION_END
89		: /* no outputs */
90		: "a" (sem1)
91		: "memory");
92}
93
94static inline int down_interruptible(struct semaphore *sem)
95{
96	register struct semaphore *sem1 __asm__ ("%a1") = sem;
97	register int result __asm__ ("%d0");
98
99	might_sleep();
100	__asm__ __volatile__(
101		"| atomic interruptible down operation\n\t"
102		"subql #1,%1@\n\t"
103		"jmi 2f\n\t"
104		"clrl %0\n"
105		"1:\n"
106		LOCK_SECTION_START(".even\n\t")
107		"2:\tpea 1b\n\t"
108		"jbra __down_failed_interruptible\n"
109		LOCK_SECTION_END
110		: "=d" (result)
111		: "a" (sem1)
112		: "memory");
113	return result;
114}
115
116static inline int down_trylock(struct semaphore *sem)
117{
118	register struct semaphore *sem1 __asm__ ("%a1") = sem;
119	register int result __asm__ ("%d0");
120
121	__asm__ __volatile__(
122		"| atomic down trylock operation\n\t"
123		"subql #1,%1@\n\t"
124		"jmi 2f\n\t"
125		"clrl %0\n"
126		"1:\n"
127		LOCK_SECTION_START(".even\n\t")
128		"2:\tpea 1b\n\t"
129		"jbra __down_failed_trylock\n"
130		LOCK_SECTION_END
131		: "=d" (result)
132		: "a" (sem1)
133		: "memory");
134	return result;
135}
136
137/*
138 * Note! This is subtle. We jump to wake people up only if
139 * the semaphore was negative (== somebody was waiting on it).
140 * The default case (no contention) will result in NO
141 * jumps for both down() and up().
142 */
143static inline void up(struct semaphore *sem)
144{
145	register struct semaphore *sem1 __asm__ ("%a1") = sem;
146
147	__asm__ __volatile__(
148		"| atomic up operation\n\t"
149		"addql #1,%0@\n\t"
150		"jle 2f\n"
151		"1:\n"
152		LOCK_SECTION_START(".even\n\t")
153		"2:\t"
154		"pea 1b\n\t"
155		"jbra __up_wakeup\n"
156		LOCK_SECTION_END
157		: /* no outputs */
158		: "a" (sem1)
159		: "memory");
160}
161
162#endif /* __ASSEMBLY__ */
163
164#endif
165