Project

General

Profile

Download (6.45 KB) Statistics
| Branch: | Tag: | Revision:
1
/*
2
 * Copyright 1995, Russell King.
3
 * Various bits and pieces copyrights include:
4
 *  Linus Torvalds (test_bit).
5
 * Big endian support: Copyright 2001, Nicolas Pitre
6
 *  reworked by rmk.
7
 *
8
 * bit 0 is the LSB of an "unsigned long" quantity.
9
 *
10
 * Please note that the code in this file should never be included
11
 * from user space.  Many of these are not implemented in assembler
12
 * since they would be too costly.  Also, they require privileged
13
 * instructions (which are not available from user mode) to ensure
14
 * that they are atomic.
15
 */
16

    
17
#ifndef __ASM_ARM_BITOPS_H
18
#define __ASM_ARM_BITOPS_H
19

    
20
#include <asm/system.h>
21

    
22
#define smp_mb__before_clear_bit()	mb()
23
#define smp_mb__after_clear_bit()	mb()
24

    
25
/*
26
 * These functions are the basis of our bit ops.
27
 *
28
 * First, the atomic bitops. These use native endian.
29
 */
30
static inline void ____atomic_set_bit(unsigned int bit, volatile unsigned long *p)
31
{
32
	unsigned long flags;
33
	unsigned long mask = 1UL << (bit & 31);
34

    
35
	p += bit >> 5;
36

    
37
	local_irq_save(flags);
38
	*p |= mask;
39
	local_irq_restore(flags);
40
}
41

    
42
static inline void ____atomic_clear_bit(unsigned int bit, volatile unsigned long *p)
43
{
44
	unsigned long flags;
45
	unsigned long mask = 1UL << (bit & 31);
46

    
47
	p += bit >> 5;
48

    
49
	local_irq_save(flags);
50
	*p &= ~mask;
51
	local_irq_restore(flags);
52
}
53

    
54
static inline void ____atomic_change_bit(unsigned int bit, volatile unsigned long *p)
55
{
56
	unsigned long flags;
57
	unsigned long mask = 1UL << (bit & 31);
58

    
59
	p += bit >> 5;
60

    
61
	local_irq_save(flags);
62
	*p ^= mask;
63
	local_irq_restore(flags);
64
}
65

    
66
static inline int
67
____atomic_test_and_set_bit(unsigned int bit, volatile unsigned long *p)
68
{
69
	unsigned long flags;
70
	unsigned int res;
71
	unsigned long mask = 1UL << (bit & 31);
72

    
73
	p += bit >> 5;
74

    
75
	local_irq_save(flags);
76
	res = *p;
77
	*p = res | mask;
78
	local_irq_restore(flags);
79

    
80
	return res & mask;
81
}
82

    
83
static inline int
84
____atomic_test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
85
{
86
	unsigned long flags;
87
	unsigned int res;
88
	unsigned long mask = 1UL << (bit & 31);
89

    
90
	p += bit >> 5;
91

    
92
	local_irq_save(flags);
93
	res = *p;
94
	*p = res & ~mask;
95
	local_irq_restore(flags);
96

    
97
	return res & mask;
98
}
99

    
100
static inline int
101
____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p)
102
{
103
	unsigned long flags;
104
	unsigned int res;
105
	unsigned long mask = 1UL << (bit & 31);
106

    
107
	p += bit >> 5;
108

    
109
	local_irq_save(flags);
110
	res = *p;
111
	*p = res ^ mask;
112
	local_irq_restore(flags);
113

    
114
	return res & mask;
115
}
116

    
117
//#include <asm-generic/bitops/non-atomic.h>
118

    
119
/*
120
 *  A note about Endian-ness.
121
 *  -------------------------
122
 *
123
 * When the ARM is put into big endian mode via CR15, the processor
124
 * merely swaps the order of bytes within words, thus:
125
 *
126
 *          ------------ physical data bus bits -----------
127
 *          D31 ... D24  D23 ... D16  D15 ... D8  D7 ... D0
128
 * little     byte 3       byte 2       byte 1      byte 0
129
 * big        byte 0       byte 1       byte 2      byte 3
130
 *
131
 * This means that reading a 32-bit word at address 0 returns the same
132
 * value irrespective of the endian mode bit.
133
 *
134
 * Peripheral devices should be connected with the data bus reversed in
135
 * "Big Endian" mode.  ARM Application Note 61 is applicable, and is
136
 * available from http://www.arm.com/.
137
 *
138
 * The following assumes that the data bus connectivity for big endian
139
 * mode has been followed.
140
 *
141
 * Note that bit 0 is defined to be 32-bit word bit 0, not byte 0 bit 0.
142
 */
143

    
144
/*
145
 * Little endian assembly bitops.  nr = 0 -> byte 0 bit 0.
146
 */
147
extern void _set_bit_le(int nr, volatile unsigned long * p);
148
extern void _clear_bit_le(int nr, volatile unsigned long * p);
149
extern void _change_bit_le(int nr, volatile unsigned long * p);
150
extern int _test_and_set_bit_le(int nr, volatile unsigned long * p);
151
extern int _test_and_clear_bit_le(int nr, volatile unsigned long * p);
152
extern int _test_and_change_bit_le(int nr, volatile unsigned long * p);
153
extern int _find_first_zero_bit_le(const void * p, unsigned size);
154
extern int _find_next_zero_bit_le(const void * p, int size, int offset);
155
extern int _find_first_bit_le(const unsigned long *p, unsigned size);
156
extern int _find_next_bit_le(const unsigned long *p, int size, int offset);
157

    
158
/*
159
 * Big endian assembly bitops.  nr = 0 -> byte 3 bit 0.
160
 */
161
extern void _set_bit_be(int nr, volatile unsigned long * p);
162
extern void _clear_bit_be(int nr, volatile unsigned long * p);
163
extern void _change_bit_be(int nr, volatile unsigned long * p);
164
extern int _test_and_set_bit_be(int nr, volatile unsigned long * p);
165
extern int _test_and_clear_bit_be(int nr, volatile unsigned long * p);
166
extern int _test_and_change_bit_be(int nr, volatile unsigned long * p);
167
extern int _find_first_zero_bit_be(const void * p, unsigned size);
168
extern int _find_next_zero_bit_be(const void * p, int size, int offset);
169
extern int _find_first_bit_be(const unsigned long *p, unsigned size);
170
extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
171

    
172
/*
173
 * The __* form of bitops are non-atomic and may be reordered.
174
 */
175
#define	ATOMIC_BITOP_LE(name,nr,p)		\
176
	(__builtin_constant_p(nr) ?		\
177
	 ____atomic_##name(nr, p) :		\
178
	 _##name##_le(nr,p))
179

    
180
#define	ATOMIC_BITOP_BE(name,nr,p)		\
181
	(__builtin_constant_p(nr) ?		\
182
	 ____atomic_##name(nr, p) :		\
183
	 _##name##_be(nr,p))
184

    
185
#define NONATOMIC_BITOP(name,nr,p)		\
186
	(____nonatomic_##name(nr, p))
187

    
188
/*
189
 * These are the little endian, atomic definitions.
190
 */
191
#define set_bit(nr,p)			ATOMIC_BITOP_LE(set_bit,nr,p)
192
#define clear_bit(nr,p)			ATOMIC_BITOP_LE(clear_bit,nr,p)
193
#define change_bit(nr,p)		ATOMIC_BITOP_LE(change_bit,nr,p)
194
#define test_and_set_bit(nr,p)		ATOMIC_BITOP_LE(test_and_set_bit,nr,p)
195
#define test_and_clear_bit(nr,p)	ATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
196
#define test_and_change_bit(nr,p)	ATOMIC_BITOP_LE(test_and_change_bit,nr,p)
197
#define find_first_zero_bit(p,sz)	_find_first_zero_bit_le(p,sz)
198
#define find_next_zero_bit(p,sz,off)	_find_next_zero_bit_le(p,sz,off)
199
#define find_first_bit(p,sz)		_find_first_bit_le(p,sz)
200
#define find_next_bit(p,sz,off)		_find_next_bit_le(p,sz,off)
201

    
202
#define WORD_BITOFF_TO_LE(x)		((x))
203

    
204
#if 0
205
#include <asm-generic/bitops/ffz.h>
206
#include <asm-generic/bitops/__ffs.h>
207
#include <asm-generic/bitops/fls.h>
208
#include <asm-generic/bitops/ffs.h>
209

    
210
#include <asm-generic/bitops/fls64.h>
211

    
212
#include <asm-generic/bitops/sched.h>
213
#include <asm-generic/bitops/hweight.h>
214
#endif
215

    
216
#define BITS_PER_LONG		32
217
#define BITOP_MASK(nr)          (1UL << ((nr) % BITS_PER_LONG))
218
#define BITOP_WORD(nr)          ((nr) / BITS_PER_LONG)
219

    
220
static inline int test_bit(int nr, const volatile unsigned long *addr)
221
{
222
	return 1UL & (addr[BITOP_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
223
}
224

    
225
#endif /* _ARM_BITOPS_H */
(3-3/9)
Add picture from clipboard (Maximum size: 48.8 MB)