aboutsummaryrefslogblamecommitdiffstats
path: root/lib/bitmap.c
blob: fb9371fdd44a43c4e8e4fc9304f0ee00d3b4df8c (plain) (tree)


































































































































































































































































































                                                                                

























                                                                                          
                                                



















































































































































































































































































                                                                                
/*
 * lib/bitmap.c
 * Helper functions for bitmap.h.
 *
 * This source code is licensed under the GNU General Public License,
 * Version 2.  See the file COPYING for more details.
 */
#include <linux/module.h>
#include <linux/ctype.h>
#include <linux/errno.h>
#include <linux/bitmap.h>
#include <linux/bitops.h>
#include <asm/uaccess.h>

/*
 * bitmaps provide an array of bits, implemented using an an
 * array of unsigned longs.  The number of valid bits in a
 * given bitmap does _not_ need to be an exact multiple of
 * BITS_PER_LONG.
 *
 * The possible unused bits in the last, partially used word
 * of a bitmap are 'don't care'.  The implementation makes
 * no particular effort to keep them zero.  It ensures that
 * their value will not affect the results of any operation.
 * The bitmap operations that return Boolean (bitmap_empty,
 * for example) or scalar (bitmap_weight, for example) results
 * carefully filter out these unused bits from impacting their
 * results.
 *
 * These operations actually hold to a slightly stronger rule:
 * if you don't input any bitmaps to these ops that have some
 * unused bits set, then they won't output any set unused bits
 * in output bitmaps.
 *
 * The byte ordering of bitmaps is more natural on little
 * endian architectures.  See the big-endian headers
 * include/asm-ppc64/bitops.h and include/asm-s390/bitops.h
 * for the best explanations of this ordering.
 */

int __bitmap_empty(const unsigned long *bitmap, int bits)
{
	int k, lim = bits/BITS_PER_LONG;
	for (k = 0; k < lim; ++k)
		if (bitmap[k])
			return 0;

	if (bits % BITS_PER_LONG)
		if (bitmap[k] & BITMAP_LAST_WORD_MASK(bits))
			return 0;

	return 1;
}
EXPORT_SYMBOL(__bitmap_empty);

int __bitmap_full(const unsigned long *bitmap, int bits)
{
	int k, lim = bits/BITS_PER_LONG;
	for (k = 0; k < lim; ++k)
		if (~bitmap[k])
			return 0;

	if (bits % BITS_PER_LONG)
		if (~bitmap[k] & BITMAP_LAST_WORD_MASK(bits))
			return 0;

	return 1;
}
EXPORT_SYMBOL(__bitmap_full);

int __bitmap_equal(const unsigned long *bitmap1,
		const unsigned long *bitmap2, int bits)
{
	int k, lim = bits/BITS_PER_LONG;
	for (k = 0; k < lim; ++k)
		if (bitmap1[k] != bitmap2[k])
			return 0;

	if (bits % BITS_PER_LONG)
		if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
			return 0;

	return 1;
}
EXPORT_SYMBOL(__bitmap_equal);

void __bitmap_complement(unsigned long *dst, const unsigned long *src, int bits)
{
	int k, lim = bits/BITS_PER_LONG;
	for (k = 0; k < lim; ++k)
		dst[k] = ~src[k];

	if (bits % BITS_PER_LONG)
		dst[k] = ~src[k] & BITMAP_LAST_WORD_MASK(bits);
}
EXPORT_SYMBOL(__bitmap_complement);

/*
 * __bitmap_shift_right - logical right shift of the bits in a bitmap
 *   @dst - destination bitmap
 *   @src - source bitmap
 *   @nbits - shift by this many bits
 *   @bits - bitmap size, in bits
 *
 * Shifting right (dividing) means moving bits in the MS -> LS bit
 * direction.  Zeros are fed into the vacated MS positions and the
 * LS bits shifted off the bottom are lost.
 */
void __bitmap_shift_right(unsigned long *dst,
			const unsigned long *src, int shift, int bits)
{
	int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG;
	int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
	unsigned long mask = (1UL << left) - 1;
	for (k = 0; off + k < lim; ++k) {
		unsigned long upper, lower;

		/*
		 * If shift is not word aligned, take lower rem bits of
		 * word above and make them the top rem bits of result.
		 */
		if (!rem || off + k + 1 >= lim)
			upper = 0;
		else {
			upper = src[off + k + 1];
			if (off + k + 1 == lim - 1 && left)
				upper &= mask;
		}
		lower = src[off + k];
		if (left && off + k == lim - 1)
			lower &= mask;
		dst[k] = upper << (BITS_PER_LONG - rem) | lower >> rem;
		if (left && k == lim - 1)
			dst[k] &= mask;
	}
	if (off)
		memset(&dst[lim - off], 0, off*sizeof(unsigned long));
}
EXPORT_SYMBOL(__bitmap_shift_right);


/*
 * __bitmap_shift_left - logical left shift of the bits in a bitmap
 *   @dst - destination bitmap
 *   @src - source bitmap
 *   @nbits - shift by this many bits
 *   @bits - bitmap size, in bits
 *
 * Shifting left (multiplying) means moving bits in the LS -> MS
 * direction.  Zeros are fed into the vacated LS bit positions
 * and those MS bits shifted off the top are lost.
 */

void __bitmap_shift_left(unsigned long *dst,
			const unsigned long *src, int shift, int bits)
{
	int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG;
	int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
	for (k = lim - off - 1; k >= 0; --k) {
		unsigned long upper, lower;

		/*
		 * If shift is not word aligned, take upper rem bits of
		 * word below and make them the bottom rem bits of result.
		 */
		if (rem && k > 0)
			lower = src[k - 1];
		else
			lower = 0;
		upper = src[k];
		if (left && k == lim - 1)
			upper &= (1UL << left) - 1;
		dst[k + off] = lower  >> (BITS_PER_LONG - rem) | upper << rem;
		if (left && k + off == lim - 1)
			dst[k + off] &= (1UL << left) - 1;
	}
	if (off)
		memset(dst, 0, off*sizeof(unsigned long));
}
EXPORT_SYMBOL(__bitmap_shift_left);

void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
				const unsigned long *bitmap2, int bits)
{
	int k;
	int nr = BITS_TO_LONGS(bits);

	for (k = 0; k < nr; k++)
		dst[k] = bitmap1[k] & bitmap2[k];
}
EXPORT_SYMBOL(__bitmap_and);

void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
				const unsigned long *bitmap2, int bits)
{
	int k;
	int nr = BITS_TO_LONGS(bits);

	for (k = 0; k < nr; k++)
		dst[k] = bitmap1[k] | bitmap2[k];
}
EXPORT_SYMBOL(__bitmap_or);

void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
				const unsigned long *bitmap2, int bits)
{
	int k;
	int nr = BITS_TO_LONGS(bits);

	for (k = 0; k < nr; k++)
		dst[k] = bitmap1[k] ^ bitmap2[k];
}
EXPORT_SYMBOL(__bitmap_xor);

void __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
				const unsigned long *bitmap2, int bits)
{
	int k;
	int nr = BITS_TO_LONGS(bits);

	for (k = 0; k < nr; k++)
		dst[k] = bitmap1[k] & ~bitmap2[k];
}
EXPORT_SYMBOL(__bitmap_andnot);

int __bitmap_intersects(const unsigned long *bitmap1,
				const unsigned long *bitmap2, int bits)
{
	int k, lim = bits/BITS_PER_LONG;
	for (k = 0; k < lim; ++k)
		if (bitmap1[k] & bitmap2[k])
			return 1;

	if (bits % BITS_PER_LONG)
		if ((bitmap1[k] & bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
			return 1;
	return 0;
}
EXPORT_SYMBOL(__bitmap_intersects);

int __bitmap_subset(const unsigned long *bitmap1,
				const unsigned long *bitmap2, int bits)
{
	int k, lim = bits/BITS_PER_LONG;
	for (k = 0; k < lim; ++k)
		if (bitmap1[k] & ~bitmap2[k])
			return 0;

	if (bits % BITS_PER_LONG)
		if ((bitmap1[k] & ~bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
			return 0;
	return 1;
}
EXPORT_SYMBOL(__bitmap_subset);

#if BITS_PER_LONG == 32
int __bitmap_weight(const unsigned long *bitmap, int bits)
{
	int k, w = 0, lim = bits/BITS_PER_LONG;

	for (k = 0; k < lim; k++)
		w += hweight32(bitmap[k]);

	if (bits % BITS_PER_LONG)
		w += hweight32(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));

	return w;
}
#else
int __bitmap_weight(const unsigned long *bitmap, int bits)
{
	int k, w = 0, lim = bits/BITS_PER_LONG;

	for (k = 0; k < lim; k++)
		w += hweight64(bitmap[k]);

	if (bits % BITS_PER_LONG)
		w += hweight64(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));

	return w;
}
#endif
EXPORT_SYMBOL(__bitmap_weight);

/*
 * Bitmap printing & parsing functions: first version by Bill Irwin,
 * second version by Paul Jackson, third by Joe Korty.
 */

#define CHUNKSZ				32
#define nbits_to_hold_value(val)	fls(val)
#define unhex(c)			(isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10))
#define BASEDEC 10		/* fancier cpuset lists input in decimal */

/**
 * bitmap_scnprintf - convert bitmap to an ASCII hex string.
 * @buf: byte buffer into which string is placed
 * @buflen: reserved size of @buf, in bytes
 * @maskp: pointer to bitmap to convert
 * @nmaskbits: size of bitmap, in bits
 *
 * Exactly @nmaskbits bits are displayed.  Hex digits are grouped into
 * comma-separated sets of eight digits per set.
 */
int bitmap_scnprintf(char *buf, unsigned int buflen,
	const unsigned long *maskp, int nmaskbits)
{
	int i, word, bit, len = 0;
	unsigned long val;
	const char *sep = "";
	int chunksz;
	u32 chunkmask;

	chunksz = nmaskbits & (CHUNKSZ - 1);
	if (chunksz == 0)
		chunksz = CHUNKSZ;

	i = ALIGN(nmaskbits, CHUNKSZ) - CHUNKSZ;
	for (; i >= 0; i -= CHUNKSZ) {
		chunkmask = ((1ULL << chunksz) - 1);
		word = i / BITS_PER_LONG;
		bit = i % BITS_PER_LONG;
		val = (maskp[word] >> bit) & chunkmask;
		len += scnprintf(buf+len, buflen-len, "%s%0*lx", sep,
			(chunksz+3)/4, val);
		chunksz = CHUNKSZ;
		sep = ",";
	}
	return len;
}
EXPORT_SYMBOL(bitmap_scnprintf);

/**
 * bitmap_parse - convert an ASCII hex string into a bitmap.
 * @buf: pointer to buffer in user space containing string.
 * @buflen: buffer size in bytes.  If string is smaller than this
 *    then it must be terminated with a \0.
 * @maskp: pointer to bitmap array that will contain result.
 * @nmaskbits: size of bitmap, in bits.
 *
 * Commas group hex digits into chunks.  Each chunk defines exactly 32
 * bits of the resultant bitmask.  No chunk may specify a value larger
 * than 32 bits (-EOVERFLOW), and if a chunk specifies a smaller value
 * then leading 0-bits are prepended.  -EINVAL is returned for illegal
 * characters and for grouping errors such as "1,,5", ",44", "," and "".
 * Leading and trailing whitespace accepted, but not embedded whitespace.
 */
int bitmap_parse(const char __user *ubuf, unsigned int ubuflen,
        unsigned long *maskp, int nmaskbits)
{
	int c, old_c, totaldigits, ndigits, nchunks, nbits;
	u32 chunk;

	bitmap_zero(maskp, nmaskbits);

	nchunks = nbits = totaldigits = c = 0;
	do {
		chunk = ndigits = 0;

		/* Get the next chunk of the bitmap */
		while (ubuflen) {
			old_c = c;
			if (get_user(c, ubuf++))
				return -EFAULT;
			ubuflen--;
			if (isspace(c))
				continue;

			/*
			 * If the last character was a space and the current
			 * character isn't '\0', we've got embedded whitespace.
			 * This is a no-no, so throw an error.
			 */
			if (totaldigits && c && isspace(old_c))
				return -EINVAL;

			/* A '\0' or a ',' signal the end of the chunk */
			if (c == '\0' || c == ',')
				break;

			if (!isxdigit(c))
				return -EINVAL;

			/*
			 * Make sure there are at least 4 free bits in 'chunk'.
			 * If not, this hexdigit will overflow 'chunk', so
			 * throw an error.
			 */
			if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1))
				return -EOVERFLOW;

			chunk = (chunk << 4) | unhex(c);
			ndigits++; totaldigits++;
		}
		if (ndigits == 0)
			return -EINVAL;
		if (nchunks == 0 && chunk == 0)
			continue;

		__bitmap_shift_left(maskp, maskp, CHUNKSZ, nmaskbits);
		*maskp |= chunk;
		nchunks++;
		nbits += (nchunks == 1) ? nbits_to_hold_value(chunk) : CHUNKSZ;
		if (nbits > nmaskbits)
			return -EOVERFLOW;
	} while (ubuflen && c == ',');

	return 0;
}
EXPORT_SYMBOL(bitmap_parse);

/*
 * bscnl_emit(buf, buflen, rbot, rtop, bp)
 *
 * Helper routine for bitmap_scnlistprintf().  Write decimal number
 * or range to buf, suppressing output past buf+buflen, with optional
 * comma-prefix.  Return len of what would be written to buf, if it
 * all fit.
 */
static inline int bscnl_emit(char *buf, int buflen, int rbot, int rtop, int len)
{
	if (len > 0)
		len += scnprintf(buf + len, buflen - len, ",");
	if (rbot == rtop)
		len += scnprintf(buf + len, buflen - len, "%d", rbot);
	else
		len += scnprintf(buf + len, buflen - len, "%d-%d", rbot, rtop);
	return len;
}

/**
 * bitmap_scnlistprintf - convert bitmap to list format ASCII string
 * @buf: byte buffer into which string is placed
 * @buflen: reserved size of @buf, in bytes
 * @maskp: pointer to bitmap to convert
 * @nmaskbits: size of bitmap, in bits
 *
 * Output format is a comma-separated list of decimal numbers and
 * ranges.  Consecutively set bits are shown as two hyphen-separated
 * decimal numbers, the smallest and largest bit numbers set in
 * the range.  Output format is compatible with the format
 * accepted as input by bitmap_parselist().
 *
 * The return value is the number of characters which would be
 * generated for the given input, excluding the trailing '\0', as
 * per ISO C99.
 */
int bitmap_scnlistprintf(char *buf, unsigned int buflen,
	const unsigned long *maskp, int nmaskbits)
{
	int len = 0;
	/* current bit is 'cur', most recently seen range is [rbot, rtop] */
	int cur, rbot, rtop;

	rbot = cur = find_first_bit(maskp, nmaskbits);
	while (cur < nmaskbits) {
		rtop = cur;
		cur = find_next_bit(maskp, nmaskbits, cur+1);
		if (cur >= nmaskbits || cur > rtop + 1) {
			len = bscnl_emit(buf, buflen, rbot, rtop, len);
			rbot = cur;
		}
	}
	return len;
}
EXPORT_SYMBOL(bitmap_scnlistprintf);

/**
 * bitmap_parselist - convert list format ASCII string to bitmap
 * @buf: read nul-terminated user string from this buffer
 * @mask: write resulting mask here
 * @nmaskbits: number of bits in mask to be written
 *
 * Input format is a comma-separated list of decimal numbers and
 * ranges.  Consecutively set bits are shown as two hyphen-separated
 * decimal numbers, the smallest and largest bit numbers set in
 * the range.
 *
 * Returns 0 on success, -errno on invalid input strings:
 *    -EINVAL:   second number in range smaller than first
 *    -EINVAL:   invalid character in string
 *    -ERANGE:   bit number specified too large for mask
 */
int bitmap_parselist(const char *bp, unsigned long *maskp, int nmaskbits)
{
	unsigned a, b;

	bitmap_zero(maskp, nmaskbits);
	do {
		if (!isdigit(*bp))
			return -EINVAL;
		b = a = simple_strtoul(bp, (char **)&bp, BASEDEC);
		if (*bp == '-') {
			bp++;
			if (!isdigit(*bp))
				return -EINVAL;
			b = simple_strtoul(bp, (char **)&bp, BASEDEC);
		}
		if (!(a <= b))
			return -EINVAL;
		if (b >= nmaskbits)
			return -ERANGE;
		while (a <= b) {
			set_bit(a, maskp);
			a++;
		}
		if (*bp == ',')
			bp++;
	} while (*bp != '\0' && *bp != '\n');
	return 0;
}
EXPORT_SYMBOL(bitmap_parselist);

/**
 *	bitmap_find_free_region - find a contiguous aligned mem region
 *	@bitmap: an array of unsigned longs corresponding to the bitmap
 *	@bits: number of bits in the bitmap
 *	@order: region size to find (size is actually 1<<order)
 *
 * This is used to allocate a memory region from a bitmap.  The idea is
 * that the region has to be 1<<order sized and 1<<order aligned (this
 * makes the search algorithm much faster).
 *
 * The region is marked as set bits in the bitmap if a free one is
 * found.
 *
 * Returns either beginning of region or negative error
 */
int bitmap_find_free_region(unsigned long *bitmap, int bits, int order)
{
	unsigned long mask;
	int pages = 1 << order;
	int i;

	if(pages > BITS_PER_LONG)
		return -EINVAL;

	/* make a mask of the order */
	mask = (1ul << (pages - 1));
	mask += mask - 1;

	/* run up the bitmap pages bits at a time */
	for (i = 0; i < bits; i += pages) {
		int index = i/BITS_PER_LONG;
		int offset = i - (index * BITS_PER_LONG);
		if((bitmap[index] & (mask << offset)) == 0) {
			/* set region in bimap */
			bitmap[index] |= (mask << offset);
			return i;
		}
	}
	return -ENOMEM;
}
EXPORT_SYMBOL(bitmap_find_free_region);

/**
 *	bitmap_release_region - release allocated bitmap region
 *	@bitmap: a pointer to the bitmap
 *	@pos: the beginning of the region
 *	@order: the order of the bits to release (number is 1<<order)
 *
 * This is the complement to __bitmap_find_free_region and releases
 * the found region (by clearing it in the bitmap).
 */
void bitmap_release_region(unsigned long *bitmap, int pos, int order)
{
	int pages = 1 << order;
	unsigned long mask = (1ul << (pages - 1));
	int index = pos/BITS_PER_LONG;
	int offset = pos - (index * BITS_PER_LONG);
	mask += mask - 1;
	bitmap[index] &= ~(mask << offset);
}
EXPORT_SYMBOL(bitmap_release_region);

int bitmap_allocate_region(unsigned long *bitmap, int pos, int order)
{
	int pages = 1 << order;
	unsigned long mask = (1ul << (pages - 1));
	int index = pos/BITS_PER_LONG;
	int offset = pos - (index * BITS_PER_LONG);

	/* We don't do regions of pages > BITS_PER_LONG.  The
	 * algorithm would be a simple look for multiple zeros in the
	 * array, but there's no driver today that needs this.  If you
	 * trip this BUG(), you get to code it... */
	BUG_ON(pages > BITS_PER_LONG);
	mask += mask - 1;
	if (bitmap[index] & (mask << offset))
		return -EBUSY;
	bitmap[index] |= (mask << offset);
	return 0;
}
EXPORT_SYMBOL(bitmap_allocate_region);
s="hl com">/* TX Carrier Extension */ /* RX MAC Configuration Register. * * NOTE: The RX MAC Enable bit must be cleared and polled until * zero before any other bits in this register are changed. * * Similar rules apply to the Hash Filter Enable bit when * programming the hash table registers, and the Address Filter * Enable bit when programming the address filter registers. */ #define MAC_RXCFG_ENAB 0x00000001 /* RX MAC Enable */ #define MAC_RXCFG_SPAD 0x00000002 /* Strip Pad */ #define MAC_RXCFG_SFCS 0x00000004 /* Strip FCS */ #define MAC_RXCFG_PROM 0x00000008 /* Promiscuous Mode */ #define MAC_RXCFG_PGRP 0x00000010 /* Promiscuous Group */ #define MAC_RXCFG_HFE 0x00000020 /* Hash Filter Enable */ #define MAC_RXCFG_AFE 0x00000040 /* Address Filter Enable */ #define MAC_RXCFG_DDE 0x00000080 /* Disable Discard on Error */ #define MAC_RXCFG_RCE 0x00000100 /* RX Carrier Extension */ /* MAC Control Config Register. */ #define MAC_MCCFG_SPE 0x00000001 /* Send Pause Enable */ #define MAC_MCCFG_RPE 0x00000002 /* Receive Pause Enable */ #define MAC_MCCFG_PMC 0x00000004 /* Pass MAC Control */ /* XIF Configuration Register. * * NOTE: When leaving or entering loopback mode, a global hardware * init of GEM should be performed. */ #define MAC_XIFCFG_OE 0x00000001 /* MII TX Output Driver Enable */ #define MAC_XIFCFG_LBCK 0x00000002 /* Loopback TX to RX */ #define MAC_XIFCFG_DISE 0x00000004 /* Disable RX path during TX */ #define MAC_XIFCFG_GMII 0x00000008 /* Use GMII clocks + datapath */ #define MAC_XIFCFG_MBOE 0x00000010 /* Controls MII_BUF_EN pin */ #define MAC_XIFCFG_LLED 0x00000020 /* Force LINKLED# active (low) */ #define MAC_XIFCFG_FLED 0x00000040 /* Force FDPLXLED# active (low) */ /* InterPacketGap0 Register. This 8-bit value is used as an extension * to the InterPacketGap1 Register. Specifically it contributes to the * timing of the RX-to-TX IPG. This value is ignored and presumed to * be zero for TX-to-TX IPG calculations and/or when the Enable IPG0 bit * is cleared in the TX MAC Configuration Register. * * This value in this register in terms of media byte time. * * Recommended value: 0x00 */ /* InterPacketGap1 Register. This 8-bit value defines the first 2/3 * portion of the Inter Packet Gap. * * This value in this register in terms of media byte time. * * Recommended value: 0x08 */ /* InterPacketGap2 Register. This 8-bit value defines the second 1/3 * portion of the Inter Packet Gap. * * This value in this register in terms of media byte time. * * Recommended value: 0x04 */ /* Slot Time Register. This 10-bit value specifies the slot time * parameter in units of media byte time. It determines the physical * span of the network. * * Recommended value: 0x40 */ /* Minimum Frame Size Register. This 10-bit register specifies the * smallest sized frame the TXMAC will send onto the medium, and the * RXMAC will receive from the medium. * * Recommended value: 0x40 */ /* Maximum Frame and Burst Size Register. * * This register specifies two things. First it specifies the maximum * sized frame the TXMAC will send and the RXMAC will recognize as * valid. Second, it specifies the maximum run length of a burst of * packets sent in half-duplex gigabit modes. * * Recommended value: 0x200005ee */ #define MAC_MAXFSZ_MFS 0x00007fff /* Max Frame Size */ #define MAC_MAXFSZ_MBS 0x7fff0000 /* Max Burst Size */ /* PA Size Register. This 10-bit register specifies the number of preamble * bytes which will be transmitted at the beginning of each frame. A * value of two or greater should be programmed here. * * Recommended value: 0x07 */ /* Jam Size Register. This 4-bit register specifies the duration of * the jam in units of media byte time. * * Recommended value: 0x04 */ /* Attempts Limit Register. This 8-bit register specifies the number * of attempts that the TXMAC will make to transmit a frame, before it * resets its Attempts Counter. After reaching the Attempts Limit the * TXMAC may or may not drop the frame, as determined by the NGU * (Never Give Up) and NGUL (Never Give Up Limit) bits in the TXMAC * Configuration Register. * * Recommended value: 0x10 */ /* MAX Control Type Register. This 16-bit register specifies the * "type" field of a MAC Control frame. The TXMAC uses this field to * encapsulate the MAC Control frame for transmission, and the RXMAC * uses it for decoding valid MAC Control frames received from the * network. * * Recommended value: 0x8808 */ /* MAC Address Registers. Each of these registers specify the * ethernet MAC of the interface, 16-bits at a time. Register * 0 specifies bits [47:32], register 1 bits [31:16], and register * 2 bits [15:0]. * * Registers 3 through and including 5 specify an alternate * MAC address for the interface. * * Registers 6 through and including 8 specify the MAC Control * Address, which must be the reserved multicast address for MAC * Control frames. * * Example: To program primary station address a:b:c:d:e:f into * the chip. * MAC_Address_2 = (a << 8) | b * MAC_Address_1 = (c << 8) | d * MAC_Address_0 = (e << 8) | f */ /* Address Filter Registers. Registers 0 through 2 specify bit * fields [47:32] through [15:0], respectively, of the address * filter. The Address Filter 2&1 Mask Register denotes the 8-bit * nibble mask for Address Filter Registers 2 and 1. The Address * Filter 0 Mask Register denotes the 16-bit mask for the Address * Filter Register 0. */ /* Hash Table Registers. Registers 0 through 15 specify bit fields * [255:240] through [15:0], respectively, of the hash table. */ /* Statistics Registers. All of these registers are 16-bits and * track occurrences of a specific event. GEM can be configured * to interrupt the host cpu when any of these counters overflow. * They should all be explicitly initialized to zero when the interface * is brought up. */ /* Random Number Seed Register. This 10-bit value is used as the * RNG seed inside GEM for the CSMA/CD backoff algorithm. It is * recommended to program this register to the 10 LSB of the * interfaces MAC address. */ /* Pause Timer, read-only. This 16-bit timer is used to time the pause * interval as indicated by a received pause flow control frame. * A non-zero value in this timer indicates that the MAC is currently in * the paused state. */ /* MIF Registers */ #define MIF_BBCLK 0x6200UL /* MIF Bit-Bang Clock */ #define MIF_BBDATA 0x6204UL /* MIF Bit-Band Data */ #define MIF_BBOENAB 0x6208UL /* MIF Bit-Bang Output Enable */ #define MIF_FRAME 0x620CUL /* MIF Frame/Output Register */ #define MIF_CFG 0x6210UL /* MIF Configuration Register */ #define MIF_MASK 0x6214UL /* MIF Mask Register */ #define MIF_STATUS 0x6218UL /* MIF Status Register */ #define MIF_SMACHINE 0x621CUL /* MIF State Machine Register */ /* MIF Bit-Bang Clock. This 1-bit register is used to generate the * MDC clock waveform on the MII Management Interface when the MIF is * programmed in the "Bit-Bang" mode. Writing a '1' after a '0' into * this register will create a rising edge on the MDC, while writing * a '0' after a '1' will create a falling edge. For every bit that * is transferred on the management interface, both edges have to be * generated. */ /* MIF Bit-Bang Data. This 1-bit register is used to generate the * outgoing data (MDO) on the MII Management Interface when the MIF * is programmed in the "Bit-Bang" mode. The daa will be steered to the * appropriate MDIO based on the state of the PHY_Select bit in the MIF * Configuration Register. */ /* MIF Big-Band Output Enable. THis 1-bit register is used to enable * ('1') or disable ('0') the I-directional driver on the MII when the * MIF is programmed in the "Bit-Bang" mode. The MDIO should be enabled * when data bits are transferred from the MIF to the transceiver, and it * should be disabled when the interface is idle or when data bits are * transferred from the transceiver to the MIF (data portion of a read * instruction). Only one MDIO will be enabled at a given time, depending * on the state of the PHY_Select bit in the MIF Configuration Register. */ /* MIF Configuration Register. This 15-bit register controls the operation * of the MIF. */ #define MIF_CFG_PSELECT 0x00000001 /* Xcvr slct: 0=mdio0 1=mdio1 */ #define MIF_CFG_POLL 0x00000002 /* Enable polling mechanism */ #define MIF_CFG_BBMODE 0x00000004 /* 1=bit-bang 0=frame mode */ #define MIF_CFG_PRADDR 0x000000f8 /* Xcvr poll register address */ #define MIF_CFG_MDI0 0x00000100 /* MDIO_0 present or read-bit */ #define MIF_CFG_MDI1 0x00000200 /* MDIO_1 present or read-bit */ #define MIF_CFG_PPADDR 0x00007c00 /* Xcvr poll PHY address */ /* MIF Frame/Output Register. This 32-bit register allows the host to * communicate with a transceiver in frame mode (as opposed to big-bang * mode). Writes by the host specify an instrution. After being issued * the host must poll this register for completion. Also, after * completion this register holds the data returned by the transceiver * if applicable. */ #define MIF_FRAME_ST 0xc0000000 /* STart of frame */ #define MIF_FRAME_OP 0x30000000 /* OPcode */ #define MIF_FRAME_PHYAD 0x0f800000 /* PHY ADdress */ #define MIF_FRAME_REGAD 0x007c0000 /* REGister ADdress */ #define MIF_FRAME_TAMSB 0x00020000 /* Turn Around MSB */ #define MIF_FRAME_TALSB 0x00010000 /* Turn Around LSB */ #define MIF_FRAME_DATA 0x0000ffff /* Instruction Payload */ /* MIF Status Register. This register reports status when the MIF is * operating in the poll mode. The poll status field is auto-clearing * on read. */ #define MIF_STATUS_DATA 0xffff0000 /* Live image of XCVR reg */ #define MIF_STATUS_STAT 0x0000ffff /* Which bits have changed */ /* MIF Mask Register. This 16-bit register is used when in poll mode * to say which bits of the polled register will cause an interrupt * when changed. */ /* PCS/Serialink Registers */ #define PCS_MIICTRL 0x9000UL /* PCS MII Control Register */ #define PCS_MIISTAT 0x9004UL /* PCS MII Status Register */ #define PCS_MIIADV 0x9008UL /* PCS MII Advertisement Reg */ #define PCS_MIILP 0x900CUL /* PCS MII Link Partner Ability */ #define PCS_CFG 0x9010UL /* PCS Configuration Register */ #define PCS_SMACHINE 0x9014UL /* PCS State Machine Register */ #define PCS_ISTAT 0x9018UL /* PCS Interrupt Status Reg */ #define PCS_DMODE 0x9050UL /* Datapath Mode Register */ #define PCS_SCTRL 0x9054UL /* Serialink Control Register */ #define PCS_SOS 0x9058UL /* Shared Output Select Reg */ #define PCS_SSTATE 0x905CUL /* Serialink State Register */ /* PCD MII Control Register. */ #define PCS_MIICTRL_SPD 0x00000040 /* Read as one, writes ignored */ #define PCS_MIICTRL_CT 0x00000080 /* Force COL signal active */ #define PCS_MIICTRL_DM 0x00000100 /* Duplex mode, forced low */ #define PCS_MIICTRL_RAN 0x00000200 /* Restart auto-neg, self clear */ #define PCS_MIICTRL_ISO 0x00000400 /* Read as zero, writes ignored */ #define PCS_MIICTRL_PD 0x00000800 /* Read as zero, writes ignored */ #define PCS_MIICTRL_ANE 0x00001000 /* Auto-neg enable */ #define PCS_MIICTRL_SS 0x00002000 /* Read as zero, writes ignored */ #define PCS_MIICTRL_WB 0x00004000 /* Wrapback, loopback at 10-bit * input side of Serialink */ #define PCS_MIICTRL_RST 0x00008000 /* Resets PCS, self clearing */ /* PCS MII Status Register. */ #define PCS_MIISTAT_EC 0x00000001 /* Ext Capability: Read as zero */ #define PCS_MIISTAT_JD 0x00000002 /* Jabber Detect: Read as zero */ #define PCS_MIISTAT_LS 0x00000004 /* Link Status: 1=up 0=down */ #define PCS_MIISTAT_ANA 0x00000008 /* Auto-neg Ability, always 1 */ #define PCS_MIISTAT_RF 0x00000010 /* Remote Fault */ #define PCS_MIISTAT_ANC 0x00000020 /* Auto-neg complete */ #define PCS_MIISTAT_ES 0x00000100 /* Extended Status, always 1 */ /* PCS MII Advertisement Register. */ #define PCS_MIIADV_FD 0x00000020 /* Advertise Full Duplex */ #define PCS_MIIADV_HD 0x00000040 /* Advertise Half Duplex */ #define PCS_MIIADV_SP 0x00000080 /* Advertise Symmetric Pause */ #define PCS_MIIADV_AP 0x00000100 /* Advertise Asymmetric Pause */ #define PCS_MIIADV_RF 0x00003000 /* Remote Fault */ #define PCS_MIIADV_ACK 0x00004000 /* Read-only */ #define PCS_MIIADV_NP 0x00008000 /* Next-page, forced low */ /* PCS MII Link Partner Ability Register. This register is equivalent * to the Link Partnet Ability Register of the standard MII register set. * It's layout corresponds to the PCS MII Advertisement Register. */ /* PCS Configuration Register. */ #define PCS_CFG_ENABLE 0x00000001 /* Must be zero while changing * PCS MII advertisement reg. */ #define PCS_CFG_SDO 0x00000002 /* Signal detect override */ #define PCS_CFG_SDL 0x00000004 /* Signal detect active low */ #define PCS_CFG_JS 0x00000018 /* Jitter-study: * 0 = normal operation * 1 = high-frequency test pattern * 2 = low-frequency test pattern * 3 = reserved */ #define PCS_CFG_TO 0x00000020 /* 10ms auto-neg timer override */ /* PCS Interrupt Status Register. This register is self-clearing * when read. */ #define PCS_ISTAT_LSC 0x00000004 /* Link Status Change */ /* Datapath Mode Register. */ #define PCS_DMODE_SM 0x00000001 /* 1 = use internal Serialink */ #define PCS_DMODE_ESM 0x00000002 /* External SERDES mode */ #define PCS_DMODE_MGM 0x00000004 /* MII/GMII mode */ #define PCS_DMODE_GMOE 0x00000008 /* GMII Output Enable */ /* Serialink Control Register. * * NOTE: When in SERDES mode, the loopback bit has inverse logic. */ #define PCS_SCTRL_LOOP 0x00000001 /* Loopback enable */ #define PCS_SCTRL_ESCD 0x00000002 /* Enable sync char detection */ #define PCS_SCTRL_LOCK 0x00000004 /* Lock to reference clock */ #define PCS_SCTRL_EMP 0x00000018 /* Output driver emphasis */ #define PCS_SCTRL_STEST 0x000001c0 /* Self test patterns */ #define PCS_SCTRL_PDWN 0x00000200 /* Software power-down */ #define PCS_SCTRL_RXZ 0x00000c00 /* PLL input to Serialink */ #define PCS_SCTRL_RXP 0x00003000 /* PLL input to Serialink */ #define PCS_SCTRL_TXZ 0x0000c000 /* PLL input to Serialink */ #define PCS_SCTRL_TXP 0x00030000 /* PLL input to Serialink */ /* Shared Output Select Register. For test and debug, allows multiplexing * test outputs into the PROM address pins. Set to zero for normal * operation. */ #define PCS_SOS_PADDR 0x00000003 /* PROM Address */ /* PROM Image Space */ #define PROM_START 0x100000UL /* Expansion ROM run time access*/ #define PROM_SIZE 0x0fffffUL /* Size of ROM */ #define PROM_END 0x200000UL /* End of ROM */ /* MII definitions missing from mii.h */ #define BMCR_SPD2 0x0040 /* Gigabit enable? (bcm5411) */ #define LPA_PAUSE 0x0400 /* More PHY registers (specific to Broadcom models) */ /* MII BCM5201 MULTIPHY interrupt register */ #define MII_BCM5201_INTERRUPT 0x1A #define MII_BCM5201_INTERRUPT_INTENABLE 0x4000 #define MII_BCM5201_AUXMODE2 0x1B #define MII_BCM5201_AUXMODE2_LOWPOWER 0x0008 #define MII_BCM5201_MULTIPHY 0x1E /* MII BCM5201 MULTIPHY register bits */ #define MII_BCM5201_MULTIPHY_SERIALMODE 0x0002 #define MII_BCM5201_MULTIPHY_SUPERISOLATE 0x0008 /* MII BCM5400 1000-BASET Control register */ #define MII_BCM5400_GB_CONTROL 0x09 #define MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP 0x0200 /* MII BCM5400 AUXCONTROL register */ #define MII_BCM5400_AUXCONTROL 0x18 #define MII_BCM5400_AUXCONTROL_PWR10BASET 0x0004 /* MII BCM5400 AUXSTATUS register */ #define MII_BCM5400_AUXSTATUS 0x19 #define MII_BCM5400_AUXSTATUS_LINKMODE_MASK 0x0700 #define MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT 8 /* When it can, GEM internally caches 4 aligned TX descriptors * at a time, so that it can use full cacheline DMA reads. * * Note that unlike HME, there is no ownership bit in the descriptor * control word. The same functionality is obtained via the TX-Kick * and TX-Complete registers. As a result, GEM need not write back * updated values to the TX descriptor ring, it only performs reads. * * Since TX descriptors are never modified by GEM, the driver can * use the buffer DMA address as a place to keep track of allocated * DMA mappings for a transmitted packet. */ struct gem_txd { u64 control_word; u64 buffer; }; #define TXDCTRL_BUFSZ 0x0000000000007fffULL /* Buffer Size */ #define TXDCTRL_CSTART 0x00000000001f8000ULL /* CSUM Start Offset */ #define TXDCTRL_COFF 0x000000001fe00000ULL /* CSUM Stuff Offset */ #define TXDCTRL_CENAB 0x0000000020000000ULL /* CSUM Enable */ #define TXDCTRL_EOF 0x0000000040000000ULL /* End of Frame */ #define TXDCTRL_SOF 0x0000000080000000ULL /* Start of Frame */ #define TXDCTRL_INTME 0x0000000100000000ULL /* "Interrupt Me" */ #define TXDCTRL_NOCRC 0x0000000200000000ULL /* No CRC Present */ /* GEM requires that RX descriptors are provided four at a time, * aligned. Also, the RX ring may not wrap around. This means that * there will be at least 4 unused desciptor entries in the middle * of the RX ring at all times. * * Similar to HME, GEM assumes that it can write garbage bytes before * the beginning of the buffer and right after the end in order to DMA * whole cachelines. * * Unlike for TX, GEM does update the status word in the RX descriptors * when packets arrive. Therefore an ownership bit does exist in the * RX descriptors. It is advisory, GEM clears it but does not check * it in any way. So when buffers are posted to the RX ring (via the * RX Kick register) by the driver it must make sure the buffers are * truly ready and that the ownership bits are set properly. * * Even though GEM modifies the RX descriptors, it guarantees that the * buffer DMA address field will stay the same when it performs these * updates. Therefore it can be used to keep track of DMA mappings * by the host driver just as in the TX descriptor case above. */ struct gem_rxd { u64 status_word; u64 buffer; }; #define RXDCTRL_TCPCSUM 0x000000000000ffffULL /* TCP Pseudo-CSUM */ #define RXDCTRL_BUFSZ 0x000000007fff0000ULL /* Buffer Size */ #define RXDCTRL_OWN 0x0000000080000000ULL /* GEM owns this entry */ #define RXDCTRL_HASHVAL 0x0ffff00000000000ULL /* Hash Value */ #define RXDCTRL_HPASS 0x1000000000000000ULL /* Passed Hash Filter */ #define RXDCTRL_ALTMAC 0x2000000000000000ULL /* Matched ALT MAC */ #define RXDCTRL_BAD 0x4000000000000000ULL /* Frame has bad CRC */ #define RXDCTRL_FRESH(gp) \ ((((RX_BUF_ALLOC_SIZE(gp) - RX_OFFSET) << 16) & RXDCTRL_BUFSZ) | \ RXDCTRL_OWN) #define TX_RING_SIZE 128 #define RX_RING_SIZE 128 #if TX_RING_SIZE == 32 #define TXDMA_CFG_BASE TXDMA_CFG_RINGSZ_32 #elif TX_RING_SIZE == 64 #define TXDMA_CFG_BASE TXDMA_CFG_RINGSZ_64 #elif TX_RING_SIZE == 128 #define TXDMA_CFG_BASE TXDMA_CFG_RINGSZ_128 #elif TX_RING_SIZE == 256 #define TXDMA_CFG_BASE TXDMA_CFG_RINGSZ_256 #elif TX_RING_SIZE == 512 #define TXDMA_CFG_BASE TXDMA_CFG_RINGSZ_512 #elif TX_RING_SIZE == 1024 #define TXDMA_CFG_BASE TXDMA_CFG_RINGSZ_1K #elif TX_RING_SIZE == 2048 #define TXDMA_CFG_BASE TXDMA_CFG_RINGSZ_2K #elif TX_RING_SIZE == 4096 #define TXDMA_CFG_BASE TXDMA_CFG_RINGSZ_4K #elif TX_RING_SIZE == 8192 #define TXDMA_CFG_BASE TXDMA_CFG_RINGSZ_8K #else #error TX_RING_SIZE value is illegal... #endif #if RX_RING_SIZE == 32 #define RXDMA_CFG_BASE RXDMA_CFG_RINGSZ_32 #elif RX_RING_SIZE == 64 #define RXDMA_CFG_BASE RXDMA_CFG_RINGSZ_64 #elif RX_RING_SIZE == 128 #define RXDMA_CFG_BASE RXDMA_CFG_RINGSZ_128 #elif RX_RING_SIZE == 256 #define RXDMA_CFG_BASE RXDMA_CFG_RINGSZ_256 #elif RX_RING_SIZE == 512 #define RXDMA_CFG_BASE RXDMA_CFG_RINGSZ_512 #elif RX_RING_SIZE == 1024 #define RXDMA_CFG_BASE RXDMA_CFG_RINGSZ_1K #elif RX_RING_SIZE == 2048 #define RXDMA_CFG_BASE RXDMA_CFG_RINGSZ_2K #elif RX_RING_SIZE == 4096 #define RXDMA_CFG_BASE RXDMA_CFG_RINGSZ_4K #elif RX_RING_SIZE == 8192 #define RXDMA_CFG_BASE RXDMA_CFG_RINGSZ_8K #else #error RX_RING_SIZE is illegal... #endif #define NEXT_TX(N) (((N) + 1) & (TX_RING_SIZE - 1)) #define NEXT_RX(N) (((N) + 1) & (RX_RING_SIZE - 1)) #define TX_BUFFS_AVAIL(GP) \ (((GP)->tx_old <= (GP)->tx_new) ? \ (GP)->tx_old + (TX_RING_SIZE - 1) - (GP)->tx_new : \ (GP)->tx_old - (GP)->tx_new - 1) #define RX_OFFSET 2 #define RX_BUF_ALLOC_SIZE(gp) ((gp)->rx_buf_sz + 28 + RX_OFFSET + 64) #define RX_COPY_THRESHOLD 256 #if TX_RING_SIZE < 128 #define INIT_BLOCK_TX_RING_SIZE 128 #else #define INIT_BLOCK_TX_RING_SIZE TX_RING_SIZE #endif #if RX_RING_SIZE < 128 #define INIT_BLOCK_RX_RING_SIZE 128 #else #define INIT_BLOCK_RX_RING_SIZE RX_RING_SIZE #endif struct gem_init_block { struct gem_txd txd[INIT_BLOCK_TX_RING_SIZE]; struct gem_rxd rxd[INIT_BLOCK_RX_RING_SIZE]; }; enum gem_phy_type { phy_mii_mdio0, phy_mii_mdio1, phy_serialink, phy_serdes, }; enum link_state { link_down = 0, /* No link, will retry */ link_aneg, /* Autoneg in progress */ link_force_try, /* Try Forced link speed */ link_force_ret, /* Forced mode worked, retrying autoneg */ link_force_ok, /* Stay in forced mode */ link_up /* Link is up */ }; struct gem { spinlock_t lock; spinlock_t tx_lock; void __iomem *regs; int rx_new, rx_old; int tx_new, tx_old; unsigned int has_wol : 1; /* chip supports wake-on-lan */ unsigned int asleep : 1; /* chip asleep, protected by pm_mutex */ unsigned int asleep_wol : 1; /* was asleep with WOL enabled */ unsigned int opened : 1; /* driver opened, protected by pm_mutex */ unsigned int running : 1; /* chip running, protected by lock */ /* cell enable count, protected by lock */ int cell_enabled; struct mutex pm_mutex; u32 msg_enable; u32 status; struct napi_struct napi; struct net_device_stats net_stats; int tx_fifo_sz; int rx_fifo_sz; int rx_pause_off; int rx_pause_on; int rx_buf_sz; u64 pause_entered; u16 pause_last_time_recvd; u32 mac_rx_cfg; u32 swrst_base; int want_autoneg; int last_forced_speed; enum link_state lstate; struct timer_list link_timer; int timer_ticks; int wake_on_lan; struct work_struct reset_task; volatile int reset_task_pending; enum gem_phy_type phy_type; struct mii_phy phy_mii; int mii_phy_addr; struct gem_init_block *init_block; struct sk_buff *rx_skbs[RX_RING_SIZE]; struct sk_buff *tx_skbs[TX_RING_SIZE]; dma_addr_t gblock_dvma; struct pci_dev *pdev; struct net_device *dev; #if defined(CONFIG_PPC_PMAC) || defined(CONFIG_SPARC) struct device_node *of_node; #endif }; #define found_mii_phy(gp) ((gp->phy_type == phy_mii_mdio0 || gp->phy_type == phy_mii_mdio1) \ && gp->phy_mii.def && gp->phy_mii.def->ops) #define ALIGNED_RX_SKB_ADDR(addr) \ ((((unsigned long)(addr) + (64UL - 1UL)) & ~(64UL - 1UL)) - (unsigned long)(addr)) static __inline__ struct sk_buff *gem_alloc_skb(int size, gfp_t gfp_flags) { struct sk_buff *skb = alloc_skb(size + 64, gfp_flags); if (skb) { int offset = (int) ALIGNED_RX_SKB_ADDR(skb->data); if (offset) skb_reserve(skb, offset); } return skb; } #endif /* _SUNGEM_H */