Home | History | Annotate | Download | only in ext2fs
      1 /*
      2  * bitops.h --- Bitmap frobbing code.  The byte swapping routines are
      3  * 	also included here.
      4  *
      5  * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
      6  *
      7  * %Begin-Header%
      8  * This file may be redistributed under the terms of the GNU Public
      9  * License.
     10  * %End-Header%
     11  *
     12  * i386 bitops operations taken from <asm/bitops.h>, Copyright 1992,
     13  * Linus Torvalds.
     14  */
     15 
     16 
     17 extern int ext2fs_set_bit(unsigned int nr,void * addr);
     18 extern int ext2fs_clear_bit(unsigned int nr, void * addr);
     19 extern int ext2fs_test_bit(unsigned int nr, const void * addr);
     20 extern void ext2fs_fast_set_bit(unsigned int nr,void * addr);
     21 extern void ext2fs_fast_clear_bit(unsigned int nr, void * addr);
     22 extern __u16 ext2fs_swab16(__u16 val);
     23 extern __u32 ext2fs_swab32(__u32 val);
     24 extern __u64 ext2fs_swab64(__u64 val);
     25 
     26 #ifdef WORDS_BIGENDIAN
     27 #define ext2fs_cpu_to_le64(x) ext2fs_swab64((x))
     28 #define ext2fs_le64_to_cpu(x) ext2fs_swab64((x))
     29 #define ext2fs_cpu_to_le32(x) ext2fs_swab32((x))
     30 #define ext2fs_le32_to_cpu(x) ext2fs_swab32((x))
     31 #define ext2fs_cpu_to_le16(x) ext2fs_swab16((x))
     32 #define ext2fs_le16_to_cpu(x) ext2fs_swab16((x))
     33 #define ext2fs_cpu_to_be32(x) ((__u32)(x))
     34 #define ext2fs_be32_to_cpu(x) ((__u32)(x))
     35 #define ext2fs_cpu_to_be16(x) ((__u16)(x))
     36 #define ext2fs_be16_to_cpu(x) ((__u16)(x))
     37 #else
     38 #define ext2fs_cpu_to_le64(x) ((__u64)(x))
     39 #define ext2fs_le64_to_cpu(x) ((__u64)(x))
     40 #define ext2fs_cpu_to_le32(x) ((__u32)(x))
     41 #define ext2fs_le32_to_cpu(x) ((__u32)(x))
     42 #define ext2fs_cpu_to_le16(x) ((__u16)(x))
     43 #define ext2fs_le16_to_cpu(x) ((__u16)(x))
     44 #define ext2fs_cpu_to_be32(x) ext2fs_swab32((x))
     45 #define ext2fs_be32_to_cpu(x) ext2fs_swab32((x))
     46 #define ext2fs_cpu_to_be16(x) ext2fs_swab16((x))
     47 #define ext2fs_be16_to_cpu(x) ext2fs_swab16((x))
     48 #endif
     49 
     50 /*
     51  * EXT2FS bitmap manipulation routines.
     52  */
     53 
     54 /* Support for sending warning messages from the inline subroutines */
     55 extern const char *ext2fs_block_string;
     56 extern const char *ext2fs_inode_string;
     57 extern const char *ext2fs_mark_string;
     58 extern const char *ext2fs_unmark_string;
     59 extern const char *ext2fs_test_string;
     60 extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
     61 			       const char *description);
     62 extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
     63 				int code, unsigned long arg);
     64 
     65 extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
     66 extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
     67 				       blk_t block);
     68 extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
     69 
     70 extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
     71 extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
     72 				       ext2_ino_t inode);
     73 extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
     74 
     75 extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
     76 					  blk_t block);
     77 extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
     78 					    blk_t block);
     79 extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
     80 					 blk_t block);
     81 
     82 extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
     83 					  ext2_ino_t inode);
     84 extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
     85 					    ext2_ino_t inode);
     86 extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
     87 					 ext2_ino_t inode);
     88 extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
     89 extern ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
     90 extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap);
     91 extern ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
     92 
     93 extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
     94 					   blk_t block, int num);
     95 extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
     96 					     blk_t block, int num);
     97 extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
     98 					  blk_t block, int num);
     99 extern int ext2fs_test_inode_bitmap_range(ext2fs_inode_bitmap bitmap,
    100 					  ino_t inode, int num);
    101 extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
    102 						blk_t block, int num);
    103 extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
    104 						  blk_t block, int num);
    105 extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
    106 					       blk_t block, int num);
    107 extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map);
    108 
    109 /* These routines moved to gen_bitmap.c */
    110 extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
    111 					 __u32 bitno);
    112 extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
    113 					   blk_t bitno);
    114 extern int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
    115 				      blk_t bitno);
    116 extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
    117 					  blk_t block, int num);
    118 extern __u32 ext2fs_get_generic_bitmap_start(ext2fs_generic_bitmap bitmap);
    119 extern __u32 ext2fs_get_generic_bitmap_end(ext2fs_generic_bitmap bitmap);
    120 
    121 /*
    122  * The inline routines themselves...
    123  *
    124  * If NO_INLINE_FUNCS is defined, then we won't try to do inline
    125  * functions at all; they will be included as normal functions in
    126  * inline.c
    127  */
    128 #ifdef NO_INLINE_FUNCS
    129 #if (defined(__GNUC__) && (defined(__i386__) || defined(__i486__) || \
    130 			   defined(__i586__) || defined(__mc68000__)))
    131 	/* This prevents bitops.c from trying to include the C */
    132 	/* function version of these functions */
    133 #define _EXT2_HAVE_ASM_BITOPS_
    134 #endif
    135 #endif /* NO_INLINE_FUNCS */
    136 
    137 #if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
    138 #ifdef INCLUDE_INLINE_FUNCS
    139 #define _INLINE_ extern
    140 #else
    141 #ifdef __GNUC__
    142 #define _INLINE_ extern __inline__
    143 #else				/* For Watcom C */
    144 #define _INLINE_ extern inline
    145 #endif
    146 #endif
    147 
    148 /*
    149  * Fast bit set/clear functions that doesn't need to return the
    150  * previous bit value.
    151  */
    152 
    153 _INLINE_ void ext2fs_fast_set_bit(unsigned int nr,void * addr)
    154 {
    155 	unsigned char	*ADDR = (unsigned char *) addr;
    156 
    157 	ADDR += nr >> 3;
    158 	*ADDR |= (1 << (nr & 0x07));
    159 }
    160 
    161 _INLINE_ void ext2fs_fast_clear_bit(unsigned int nr, void * addr)
    162 {
    163 	unsigned char	*ADDR = (unsigned char *) addr;
    164 
    165 	ADDR += nr >> 3;
    166 	*ADDR &= ~(1 << (nr & 0x07));
    167 }
    168 
    169 
    170 #if ((defined __GNUC__) && !defined(_EXT2_USE_C_VERSIONS_) && \
    171      (defined(__i386__) || defined(__i486__) || defined(__i586__)))
    172 
    173 #define _EXT2_HAVE_ASM_BITOPS_
    174 #define _EXT2_HAVE_ASM_SWAB_
    175 
    176 /*
    177  * These are done by inline assembly for speed reasons.....
    178  *
    179  * All bitoperations return 0 if the bit was cleared before the
    180  * operation and != 0 if it was not.  Bit 0 is the LSB of addr; bit 32
    181  * is the LSB of (addr+1).
    182  */
    183 
    184 /*
    185  * Some hacks to defeat gcc over-optimizations..
    186  */
    187 struct __dummy_h { unsigned long a[100]; };
    188 #define EXT2FS_ADDR (*(struct __dummy_h *) addr)
    189 #define EXT2FS_CONST_ADDR (*(const struct __dummy_h *) addr)
    190 
    191 _INLINE_ int ext2fs_set_bit(unsigned int nr, void * addr)
    192 {
    193 	int oldbit;
    194 
    195 	addr = (void *) (((unsigned char *) addr) + (nr >> 3));
    196 	__asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0"
    197 		:"=r" (oldbit),"+m" (EXT2FS_ADDR)
    198 		:"r" (nr & 7));
    199 	return oldbit;
    200 }
    201 
    202 _INLINE_ int ext2fs_clear_bit(unsigned int nr, void * addr)
    203 {
    204 	int oldbit;
    205 
    206 	addr = (void *) (((unsigned char *) addr) + (nr >> 3));
    207 	__asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0"
    208 		:"=r" (oldbit),"+m" (EXT2FS_ADDR)
    209 		:"r" (nr & 7));
    210 	return oldbit;
    211 }
    212 
    213 _INLINE_ int ext2fs_test_bit(unsigned int nr, const void * addr)
    214 {
    215 	int oldbit;
    216 
    217 	addr = (const void *) (((const unsigned char *) addr) + (nr >> 3));
    218 	__asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
    219 		:"=r" (oldbit)
    220 		:"m" (EXT2FS_CONST_ADDR),"r" (nr & 7));
    221 	return oldbit;
    222 }
    223 
    224 _INLINE_ __u32 ext2fs_swab32(__u32 val)
    225 {
    226 #ifdef EXT2FS_REQUIRE_486
    227 	__asm__("bswap %0" : "=r" (val) : "0" (val));
    228 #else
    229 	__asm__("xchgb %b0,%h0\n\t"	/* swap lower bytes	*/
    230 		"rorl $16,%0\n\t"	/* swap words		*/
    231 		"xchgb %b0,%h0"		/* swap higher bytes	*/
    232 		:"=q" (val)
    233 		: "0" (val));
    234 #endif
    235 	return val;
    236 }
    237 
    238 _INLINE_ __u16 ext2fs_swab16(__u16 val)
    239 {
    240 	__asm__("xchgb %b0,%h0"		/* swap bytes		*/ \
    241 		: "=q" (val) \
    242 		:  "0" (val)); \
    243 		return val;
    244 }
    245 
    246 #undef EXT2FS_ADDR
    247 
    248 #endif	/* i386 */
    249 
    250 #if ((defined __GNUC__) && !defined(_EXT2_USE_C_VERSIONS_) && \
    251      (defined(__mc68000__)))
    252 
    253 #define _EXT2_HAVE_ASM_BITOPS_
    254 
    255 _INLINE_ int ext2fs_set_bit(unsigned int nr,void * addr)
    256 {
    257 	char retval;
    258 
    259 	__asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0"
    260 	     : "=d" (retval) : "d" (nr^7), "a" (addr));
    261 
    262 	return retval;
    263 }
    264 
    265 _INLINE_ int ext2fs_clear_bit(unsigned int nr, void * addr)
    266 {
    267 	char retval;
    268 
    269 	__asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0"
    270 	     : "=d" (retval) : "d" (nr^7), "a" (addr));
    271 
    272 	return retval;
    273 }
    274 
    275 _INLINE_ int ext2fs_test_bit(unsigned int nr, const void * addr)
    276 {
    277 	char retval;
    278 
    279 	__asm__ __volatile__ ("bftst %2@{%1:#1}; sne %0"
    280 	     : "=d" (retval) : "d" (nr^7), "a" (addr));
    281 
    282 	return retval;
    283 }
    284 
    285 #endif /* __mc68000__ */
    286 
    287 
    288 #if !defined(_EXT2_HAVE_ASM_SWAB_)
    289 
    290 _INLINE_ __u16 ext2fs_swab16(__u16 val)
    291 {
    292 	return (val >> 8) | (val << 8);
    293 }
    294 
    295 _INLINE_ __u32 ext2fs_swab32(__u32 val)
    296 {
    297 	return ((val>>24) | ((val>>8)&0xFF00) |
    298 		((val<<8)&0xFF0000) | (val<<24));
    299 }
    300 
    301 #endif /* !_EXT2_HAVE_ASM_SWAB */
    302 
    303 _INLINE_ __u64 ext2fs_swab64(__u64 val)
    304 {
    305 	return (ext2fs_swab32(val >> 32) |
    306 		(((__u64)ext2fs_swab32(val & 0xFFFFFFFFUL)) << 32));
    307 }
    308 
    309 _INLINE_ int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
    310 				       blk_t block)
    311 {
    312 	return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
    313 					  block);
    314 }
    315 
    316 _INLINE_ int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
    317 					 blk_t block)
    318 {
    319 	return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
    320 					    block);
    321 }
    322 
    323 _INLINE_ int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
    324 				       blk_t block)
    325 {
    326 	return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
    327 					  block);
    328 }
    329 
    330 _INLINE_ int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
    331 				       ext2_ino_t inode)
    332 {
    333 	return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
    334 					  inode);
    335 }
    336 
    337 _INLINE_ int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
    338 					 ext2_ino_t inode)
    339 {
    340 	return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
    341 				     inode);
    342 }
    343 
    344 _INLINE_ int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
    345 				       ext2_ino_t inode)
    346 {
    347 	return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
    348 					  inode);
    349 }
    350 
    351 _INLINE_ void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
    352 					    blk_t block)
    353 {
    354 	ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
    355 }
    356 
    357 _INLINE_ void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
    358 					      blk_t block)
    359 {
    360 	ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
    361 }
    362 
    363 _INLINE_ int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
    364 					    blk_t block)
    365 {
    366 	return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
    367 					  block);
    368 }
    369 
    370 _INLINE_ void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
    371 					    ext2_ino_t inode)
    372 {
    373 	ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
    374 }
    375 
    376 _INLINE_ void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
    377 					      ext2_ino_t inode)
    378 {
    379 	ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
    380 }
    381 
    382 _INLINE_ int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
    383 					   ext2_ino_t inode)
    384 {
    385 	return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
    386 					  inode);
    387 }
    388 
    389 _INLINE_ blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
    390 {
    391 	return ext2fs_get_generic_bitmap_start((ext2fs_generic_bitmap) bitmap);
    392 }
    393 
    394 _INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
    395 {
    396 	return ext2fs_get_generic_bitmap_start((ext2fs_generic_bitmap) bitmap);
    397 }
    398 
    399 _INLINE_ blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
    400 {
    401 	return ext2fs_get_generic_bitmap_end((ext2fs_generic_bitmap) bitmap);
    402 }
    403 
    404 _INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
    405 {
    406 	return ext2fs_get_generic_bitmap_end((ext2fs_generic_bitmap) bitmap);
    407 }
    408 
    409 _INLINE_ int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
    410 						 blk_t block, int num)
    411 {
    412 	return ext2fs_test_block_bitmap_range(bitmap, block, num);
    413 }
    414 
    415 _INLINE_ void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
    416 						  blk_t block, int num)
    417 {
    418 	ext2fs_mark_block_bitmap_range(bitmap, block, num);
    419 }
    420 
    421 _INLINE_ void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
    422 						    blk_t block, int num)
    423 {
    424 	ext2fs_unmark_block_bitmap_range(bitmap, block, num);
    425 }
    426 #undef _INLINE_
    427 #endif
    428 
    429