[patch] Add helper macros for little-endian bitfields

From: David Vrabel
Date: Thu Aug 21 2008 - 09:21:30 EST


--
David Vrabel, Senior Software Engineer, Drivers
CSR, Churchill House, Cambridge Business Park, Tel: +44 (0)1223 692562
Cowley Road, Cambridge, CB4 0WZ http://www.csr.com/
Add helper macros for little-endian bitfields

From: Inaky Perez-Gonzalez <inaky.perez-gonzalez@xxxxxxxxx>

This adds some macros to help in defining structures with little-endian
values with bitfields. Useful when defining hardware interfaces.

Signed-off-by: David Vrabel <david.vrabel@xxxxxxx>
---
include/linux/byteorder/bitfields.h | 114 ++++++++++++++++++++++++++++++++++++
1 file changed, 114 insertions(+)

Index: linux-2.6/include/linux/byteorder/bitfields.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/include/linux/byteorder/bitfields.h 2008-05-13 09:44:16.000000000 +0100
@@ -0,0 +1,114 @@
+/*
+ * Helpers for defining little-endian bitfields
+ *
+ * Copyright (C) 2007 Intel Corporation
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@xxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __LINUX__BYTEORDER__BITFIELDS_H__
+#define __LINUX__BYTEORDER__BITFIELDS_H__
+
+#include <asm/byteorder.h>
+
+/*
+ * Declare Little Endian bitfields
+ *
+ * These macros are used to switch the order of the bitfields when
+ * packing with Little Endian in mind (ie: for mapping to a hw type
+ * that you have to send or read from a device).
+ *
+ * NOTE: When using multibyte bitfields, you need to convert the data
+ * from Little Endian to CPU before you can access the bitfield
+ * (to make it simpler):
+ *
+ * union something {
+ * le16 value;
+ * DECL_BF_LE3(
+ * u16 bf0:3,
+ * u16 bf1:10,
+ * u16 bf2:3
+ * ) __attribute__((packed));
+ * };
+ *
+ * ...
+ *
+ * union something s;
+ *
+ * s.value = le16_to_cpu(something LE read from hw);
+ * frame_count = s.bf1;
+ *
+ */
+#ifdef __LITTLE_ENDIAN_BITFIELD
+#define DECL_BF_LE2(a, b) struct { a; b; }
+#define DECL_BF_LE3(a, b, c) struct { a; b; c; }
+#define DECL_BF_LE4(a, b, c, d) struct { a; b; c; d ; }
+#define DECL_BF_LE5(a, b, c, d, e) struct { a; b; c; d; e; }
+#define DECL_BF_LE6(a, b, c, d, e, f) struct { a; b; c; d; e; f; }
+#define DECL_BF_LE7(a, b, c, d, e, f, g) struct { a; b; c; d; e; f; g; }
+#define DECL_BF_LE8(a, b, c, d, e, f, g, h) struct { a; b; c; d; e; f; g; h; }
+#define DECL_BF_LE9(a, b, c, d, e, f, g, h, i) \
+ struct { a; b; c; d; e; f; g; h; i; }
+#define DECL_BF_LE10(a, b, c, d, e, f, g, h, i, j) \
+ struct { a; b; c; d; e; f; g; h; i; j; }
+#define DECL_BF_LE11(a, b, c, d, e, f, g, h, i, j, k) \
+ struct { a; b; c; d; e; f; g; h; i; j; k; }
+#define DECL_BF_LE12(a, b, c, d, e, f, g, h, i, j, k, l) \
+ struct { a; b; c; d; e; f; g; h; i; j; k; l; }
+#define DECL_BF_LE13(a, b, c, d, e, f, g, h, i, j, k, l, m) \
+ struct { a; b; c; d; e; f; g; h; i; j; k; l; m; }
+#define DECL_BF_LE14(a, b, c, d, e, f, g, h, i, j, k, l, m, n) \
+ struct { a; b; c; d; e; f; g; h; i; j; k; l; m; n; }
+#define DECL_BF_LE15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) \
+ struct { a; b; c; d; e; f; g; h; i; j; k; l; m; n; o; }
+#define DECL_BF_LE16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
+ struct { a; b; c; d; e; f; g; h; i; j; k; l; m; n; o; p; }
+
+#else
+#ifdef __BIG_ENDIAN_BITFIELD
+
+#define DECL_BF_LE2(a, b) struct { b; a; }
+#define DECL_BF_LE3(a, b, c) struct { c; b; a; }
+#define DECL_BF_LE4(a, b, c, d) struct { d; c; b; a; }
+#define DECL_BF_LE5(a, b, c, d, e) struct { e; d; c; b; a; }
+#define DECL_BF_LE6(a, b, c, d, e, f) struct { f; e; d; c; b; a; }
+#define DECL_BF_LE7(a, b, c, d, e, f, g) struct { g; f; e; d; c; b; a; }
+#define DECL_BF_LE8(a, b, c, d, e, f, g, h) struct { h; g; f; e; d; c; b; a; }
+#define DECL_BF_LE9(a, b, c, d, e, f, g, h, i) \
+ struct { i; h; g; f; e; d; c; b; a; }
+#define DECL_BF_LE10(a, b, c, d, e, f, g, h, i, j) \
+ struct { j; i; h; g; f; e; d; c; b; a; }
+#define DECL_BF_LE11(a, b, c, d, e, f, g, h, i, j, k) \
+ struct { k; j; i; h; g; f; e; d; c; b; a; }
+#define DECL_BF_LE12(a, b, c, d, e, f, g, h, i, j, k, l) \
+ struct { l; k; j; i; h; g; f; e; d; c; b; a; }
+#define DECL_BF_LE13(a, b, c, d, e, f, g, h, i, j, k, l, m) \
+ struct { m; l; k; j; i; h; g; f; e; d; c; b; a; }
+#define DECL_BF_LE14(a, b, c, d, e, f, g, h, i, j, k, l, m, n) \
+ struct { n; m; l; k; j; i; h; g; f; e; d; c; b; a; }
+#define DECL_BF_LE15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) \
+ struct { o; n; m; l; k; j; i; h; g; f; e; d; c; b; a; }
+#define DECL_BF_LE16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
+ struct { p; o; n; m; l; k; j; i; h; g; f; e; d; c; b; a; }
+
+#else
+
+#error Unknown endianess for Little Endian bitfield definition
+
+#endif
+#endif
+
+#endif /* #ifndef __LINUX__BYTEORDER__BITFIELDS_H__ */