patch-2.1.16 linux/include/asm-ppc/bitops.h

Next file: linux/include/asm-ppc/byteorder.h
Previous file: linux/include/asm-ppc/atomic.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.15/linux/include/asm-ppc/bitops.h linux/include/asm-ppc/bitops.h
@@ -1,39 +1,32 @@
 #ifndef _ASM_PPC_BITOPS_H_
 #define _ASM_PPC_BITOPS_H_
 
-/*
- * For the benefit of those who are trying to port Linux to another
- * architecture, here are some C-language equivalents.  You should
- * recode these in the native assembly language, if at all possible.
- * To guarantee atomicity, these routines call cli() and sti() to
- * disable interrupts while they operate.  (You have to provide inline
- * routines to cli() and sti().)
- *
- * Also note, these routines assume that you have 32 bit integers.
- * You will have to change this if you are trying to port Linux to the
- * Alpha architecture or to a Cray.  :-)
- * 
- * C language equivalents written by Theodore Ts'o, 9/26/92
- */
-
-#include "asm/system.h"  /* For cli/sti declaration */
+#include <asm/system.h>
+#include <asm/byteorder.h>
 
 #define BIT(n) 1<<(n&0x1F)
 typedef unsigned long BITFIELD;
 
+
+/* Set bit 'nr' in 32-bit quantity at address 'addr' where bit '0'
+ * is in the highest of the four bytes and bit '31' is the high bit
+ * within the first byte. powerpc is BIG-Endian. Unless noted otherwise
+ * all bit-ops return 0 if bit was previously clear and != 0 otherwise.
+ */
 extern __inline__ int set_bit(int nr, void * add)
 {
-       int	mask, oldbit;
   BITFIELD *addr = add;
-       
+	long	mask,oldbit;       
+#ifdef __KERNEL__
 	int s = _disable_interrupts();
+#endif
 	addr += nr >> 5;
 	mask = BIT(nr);
 	oldbit = (mask & *addr) != 0;
 	*addr |= mask;
+#ifdef __KERNEL__	
 	_enable_interrupts(s);
-
-	
+#endif
 	return oldbit;
 }
 
@@ -41,12 +34,16 @@
 {
   	BITFIELD *addr = add;
 	int	mask, retval;
+#ifdef __KERNEL__
 	int s = _disable_interrupts();
+#endif
 	addr += nr >> 5;
 	mask = BIT(nr);
 	retval = (mask & *addr) != 0;
 	*addr ^= mask;
+#ifdef __KERNEL__
 	_enable_interrupts(s);
+#endif
 	return retval;
 }
 
@@ -54,77 +51,115 @@
 {
         BITFIELD *addr = add;
 	int	mask, retval;
+#ifdef __KERNEL__
 	int s = _disable_interrupts();
+#endif
 	addr += nr >> 5;
 	mask = BIT(nr);
 	retval = (mask & *addr) != 0;
 	*addr &= ~mask;
+#ifdef __KERNEL__	
 	_enable_interrupts(s);
+#endif
 	return retval;
 }
 
-extern __inline__ int test_bit(int nr, void *add)
+#define _EXT2_HAVE_ASM_BITOPS_
+#define ext2_find_first_zero_bit(addr, size) \
+        ext2_find_next_zero_bit((addr), (size), 0)
+
+
+extern __inline__ int ext2_set_bit(int nr, void * addr)
 {
-	int	mask;
-	BITFIELD *addr = add;
+#ifdef __KERNEL__
+  int s = _disable_interrupts();
+#endif
+  int			mask;
+  unsigned char	*ADDR = (unsigned char *) addr;
+  int oldbit;
+  
+  ADDR += nr >> 3;
+  mask = 1 << (nr & 0x07);
+  oldbit = (*ADDR & mask) ? 1 : 0;
+  *ADDR |= mask;
+#ifdef __KERNEL__	
+  _enable_interrupts(s);
+#endif
+  return oldbit;
+}
 
-	addr += nr >> 5;
-	mask = BIT(nr);
-	return ((mask & *addr) != 0);
+extern __inline__ int ext2_clear_bit(int nr, void * addr)
+{
+#ifdef __KERNEL__
+  int s = _disable_interrupts();
+#endif
+  int		mask;
+  unsigned char	*ADDR = (unsigned char *) addr;
+  int oldbit;
+  
+  ADDR += nr >> 3;
+  mask = 1 << (nr & 0x07);
+  oldbit = (*ADDR & mask) ? 1 : 0;
+  *ADDR = *ADDR & ~mask;
+#ifdef __KERNEL__	
+  _enable_interrupts(s);
+#endif
+  return oldbit;
 }
-#if 0
-extern __inline__ int find_first_zero_bit(void *add, int len)
+
+
+/* The following routine need not be atomic. */
+extern __inline__ unsigned long test_bit(int nr, void *addr)
 {
-	int	mask, nr, i;
-	BITFIELD *addr = add;
-	nr = 0;
-	while (len)
-	{
-		if (~*addr != 0)
-		{ /* Contains at least one zero */
-			for (i = 0;  i < 32;  i++, nr++)
-			{
-				mask = BIT(nr);
-				if ((mask & *addr) == 0)
-				{
-					return (nr);
-				}
-			}
-		}
-		len -= 32;
-		addr++;
-		nr += 32;
-	}
-	return (0);  /* Shouldn't happen */
+	return 1UL & (((__const__ unsigned int *) addr)[nr >> 5] >> (nr & 31));
 }
 
-extern __inline__ int find_next_zero_bit(void *add, int len, int nr)
+extern __inline__ int ext2_test_bit(int nr, __const__ void * addr)
 {
-	int	mask, i;
-	BITFIELD *addr = add;
-	addr += nr >> 5;
-	len -= nr;
-	while (len)
-	{
-		if (*addr != 0xFFFFFFFF)
-		{ /* Contains at least one zero */
-			for (i = 0;  i < 32;  i++, nr++)
-			{
-				mask = BIT(nr);
-				if ((mask & *addr) == 0)
-				{
-printk("Bit: %d(%d), Pat: %x\n", nr, nr&0x1F, *addr);					
-					return (nr);
-				}
-			}
-		}
-		len -= 32;
-		addr++;
-		nr += 32;
+	int			mask;
+	__const__ unsigned char	*ADDR = (__const__ unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	mask = 1 << (nr & 0x07);
+	return ((mask & *ADDR) != 0);
+}
+
+extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
+{
+	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
+	unsigned long result = offset & ~31UL;
+	unsigned long tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 31UL;
+	if(offset) {
+		tmp = *(p++);
+		tmp |= le32_to_cpu(~0UL >> (32-offset));
+		if(size < 32)
+			goto found_first;
+		if(~tmp)
+			goto found_middle;
+		size -= 32;
+		result += 32;
+	}
+	while(size & ~31UL) {
+		if(~(tmp = *(p++)))
+			goto found_middle;
+		result += 32;
+		size -= 32;
 	}
-	return (0);  /* Shouldn't happen */
+	if(!size)
+		return result;
+	tmp = *p;
+
+found_first:
+	return result + ffz(le32_to_cpu(tmp) | (~0UL << size));
+found_middle:
+	return result + ffz(le32_to_cpu(tmp));
 }
-#endif
+
 #endif /* _ASM_PPC_BITOPS_H */
 
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov