//
// $Header: D:/ext2-os2/include/asm/RCS/bitops.h,v 1.5 1995/08/08 21:18:29 Willm Exp Willm $
//
// Linux ext2 file system driver for OS/2 2.x and WARP - Allows OS/2 to
// access your Linux ext2fs partitions as normal drive letters.
// OS/2 implementation : Copyright (C) 1995 Matthieu WILLM
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#ifndef _ASM_GENERIC_BITOPS_H_
#define _ASM_GENERIC_BITOPS_H_
#ifdef OS2
//
// Rewrite to the OS/2 16 bits IFS memory model- M. WILLM
//
#include <string.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
*/
extern _inline INT32 set_bit(INT32 nr,INT32 *addr)
{
INT32 mask, retval;
addr += nr >> 5L;
mask = 1L << (nr & 0x1fL);
retval = (mask & *addr) != 0L;
*addr |= mask;
return retval;
}
extern _inline INT32 test_bit(INT32 nr, INT32 *addr)
{
long mask;
addr += nr >> 5L;
mask = 1L << (nr & 0x1fL);
return ((mask & *addr) != 0L);
}
extern _inline INT32 clear_bit(INT32 nr, PINT32 addr)
{
INT32 mask, retval;
addr += nr >> 5L;
mask = 1L << (nr & 0x1fL);
retval = (mask & *addr) != 0L;
*addr &= ~mask;
return retval;
}
/*
* find the first occurrence of byte 'c', or 1 past the area if none
*/
#if 0
extern _inline void * memscan(void * cs, long c, long n) {
void * x;
x = memchr(cs, (int)c, (int)n);
return (x == NULL ? (void *)((pchar)(cs) + n) : x);
}
#else
extern _inline void * memscan(void * cs, long c, long n) {
unsigned char *x = (unsigned char *)cs;
unsigned char cc = (unsigned char)c;
long i = 0;
while ((x[i] != cc) && (i < n)) i++;
return (x[i] == cc ? x + i : x + n);
}
#endif
extern unsigned long _inline ffz(unsigned long word) {
unsigned long temp = 0;
word = ~word;
while (!test_bit(temp, &word)) temp++;
return temp;
}
extern long _inline find_first_zero_bit(void *addr, unsigned long size) {
unsigned long i = 0L, j = 0L;
unsigned long *x = (unsigned long *)addr;
size = size / 32L;
while ((i < size) && (x[i]==~0L)) i++;
if (i == size) return (i << 5L);
while ((j < 32L) && ((x[i] & (1L << j)) != 0L)) j++;
return ((i << 5L) + j );
}
extern _inline long find_next_zero_bit (void * addr, long size, long offset)
{
unsigned long * p = ((unsigned long *) addr) + (offset >> 5L);
long set = 0L, bit = offset & 31L, res;
unsigned long q = (*p) >> bit;
if (bit) {
set = find_first_zero_bit(&q, 32L);
if (set < 32L - bit) {
// if (test_bit(set + offset, addr)) FSH_INTERR("Erreur find_next_zero_bit", sizeof("Erreur find_next_zero_bit"));
return set + offset;
}
set = 32L - bit;
p++;
}
/*
* No zero yet, search remaining full bytes for a zero
*/
res = find_first_zero_bit (p, size - 32L * (p - (unsigned long *) addr));
// if (test_bit(set + offset + res, addr)) FSH_INTERR("Erreur 2 find_next_zero_bit", sizeof("Erreur 2 find_next_zero_bit"));
return (offset + set + res);
}
#else
#error "This file is OS/2 specific"
#endif
#endif /* _ASM_GENERIC_BITOPS_H */