firewire: core: add common macro to serialize/deserialize isochronous packet header
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Sun, 28 Apr 2024 07:13:45 +0000 (16:13 +0900)
committerTakashi Sakamoto <o-takashi@sakamocchi.jp>
Mon, 6 May 2024 02:06:05 +0000 (11:06 +0900)
The packet for Asynchronous Streaming Packet includes the same header
fields as the isochronous packet has. It is helpful to have some helper
functions to serialize/deserialize them.

This commit adds such helper functions with their test.

Link: https://lore.kernel.org/r/20240428071347.409202-8-o-takashi@sakamocchi.jp
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
drivers/firewire/packet-header-definitions.h
drivers/firewire/packet-serdes-test.c

index 83e550427706743f4b42ee9fd4173f4d54165a8f..ab9d0fa790d41ebf87a935fcb1b7153e09f0f83b 100644 (file)
@@ -165,4 +165,70 @@ static inline void async_header_set_extended_tcode(u32 header[ASYNC_HEADER_QUADL
        header[3] |= (((u32)extended_tcode) << ASYNC_HEADER_Q3_EXTENDED_TCODE_SHIFT) & ASYNC_HEADER_Q3_EXTENDED_TCODE_MASK;
 }
 
+#define ISOC_HEADER_DATA_LENGTH_SHIFT          16
+#define ISOC_HEADER_DATA_LENGTH_MASK           0xffff0000
+#define ISOC_HEADER_TAG_SHIFT                  14
+#define ISOC_HEADER_TAG_MASK                   0x0000c000
+#define ISOC_HEADER_CHANNEL_SHIFT              8
+#define ISOC_HEADER_CHANNEL_MASK               0x00003f00
+#define ISOC_HEADER_TCODE_SHIFT                        4
+#define ISOC_HEADER_TCODE_MASK                 0x000000f0
+#define ISOC_HEADER_SY_SHIFT                   0
+#define ISOC_HEADER_SY_MASK                    0x0000000f
+
+static inline unsigned int isoc_header_get_data_length(u32 header)
+{
+       return (header & ISOC_HEADER_DATA_LENGTH_MASK) >> ISOC_HEADER_DATA_LENGTH_SHIFT;
+}
+
+static inline unsigned int isoc_header_get_tag(u32 header)
+{
+       return (header & ISOC_HEADER_TAG_MASK) >> ISOC_HEADER_TAG_SHIFT;
+}
+
+static inline unsigned int isoc_header_get_channel(u32 header)
+{
+       return (header & ISOC_HEADER_CHANNEL_MASK) >> ISOC_HEADER_CHANNEL_SHIFT;
+}
+
+static inline unsigned int isoc_header_get_tcode(u32 header)
+{
+       return (header & ISOC_HEADER_TCODE_MASK) >> ISOC_HEADER_TCODE_SHIFT;
+}
+
+static inline unsigned int isoc_header_get_sy(u32 header)
+{
+       return (header & ISOC_HEADER_SY_MASK) >> ISOC_HEADER_SY_SHIFT;
+}
+
+static inline void isoc_header_set_data_length(u32 *header, unsigned int data_length)
+{
+       *header &= ~ISOC_HEADER_DATA_LENGTH_MASK;
+       *header |= (((u32)data_length) << ISOC_HEADER_DATA_LENGTH_SHIFT) & ISOC_HEADER_DATA_LENGTH_MASK;
+}
+
+static inline void isoc_header_set_tag(u32 *header, unsigned int tag)
+{
+       *header &= ~ISOC_HEADER_TAG_MASK;
+       *header |= (((u32)tag) << ISOC_HEADER_TAG_SHIFT) & ISOC_HEADER_TAG_MASK;
+}
+
+static inline void isoc_header_set_channel(u32 *header, unsigned int channel)
+{
+       *header &= ~ISOC_HEADER_CHANNEL_MASK;
+       *header |= (((u32)channel) << ISOC_HEADER_CHANNEL_SHIFT) & ISOC_HEADER_CHANNEL_MASK;
+}
+
+static inline void isoc_header_set_tcode(u32 *header, unsigned int tcode)
+{
+       *header &= ~ISOC_HEADER_TCODE_MASK;
+       *header |= (((u32)tcode) << ISOC_HEADER_TCODE_SHIFT) & ISOC_HEADER_TCODE_MASK;
+}
+
+static inline void isoc_header_set_sy(u32 *header, unsigned int sy)
+{
+       *header &= ~ISOC_HEADER_SY_MASK;
+       *header |= (((u32)sy) << ISOC_HEADER_SY_SHIFT) & ISOC_HEADER_SY_MASK;
+}
+
 #endif // _FIREWIRE_PACKET_HEADER_DEFINITIONS_H
index 299e9f908463cd65adf5979b4ab15150d111eadf..f93c966e794d97b914b1d681990d6f8a4109b8ae 100644 (file)
@@ -167,6 +167,26 @@ static void deserialize_async_header_block_response(const u32 header[ASYNC_HEADE
        *extended_tcode = async_header_get_extended_tcode(header);
 }
 
+static void serialize_isoc_header(u32 *header, unsigned int data_length, unsigned int tag,
+                                 unsigned int channel, unsigned int tcode, unsigned int sy)
+{
+       isoc_header_set_data_length(header, data_length);
+       isoc_header_set_tag(header, tag);
+       isoc_header_set_channel(header, channel);
+       isoc_header_set_tcode(header, tcode);
+       isoc_header_set_sy(header, sy);
+}
+
+static void deserialize_isoc_header(u32 header, unsigned int *data_length, unsigned int *tag,
+                                   unsigned int *channel, unsigned int *tcode, unsigned int *sy)
+{
+       *data_length = isoc_header_get_data_length(header);
+       *tag = isoc_header_get_tag(header);
+       *channel = isoc_header_get_channel(header);
+       *tcode = isoc_header_get_tcode(header);
+       *sy = isoc_header_get_sy(header);
+}
+
 static void test_async_header_write_quadlet_request(struct kunit *test)
 {
        static const u32 expected[ASYNC_HEADER_QUADLET_COUNT] = {
@@ -515,6 +535,29 @@ static void test_async_header_lock_response(struct kunit *test)
        KUNIT_EXPECT_MEMEQ(test, header, expected, sizeof(expected));
 }
 
+static void test_isoc_header(struct kunit *test)
+{
+       const u32 expected = 0x00d08dec;
+       u32 header = 0;
+
+       unsigned int data_length;
+       unsigned int tag;
+       unsigned int channel;
+       unsigned int tcode;
+       unsigned int sy;
+
+       deserialize_isoc_header(expected, &data_length, &tag, &channel, &tcode, &sy);
+
+       KUNIT_EXPECT_EQ(test, 0xd0, data_length);
+       KUNIT_EXPECT_EQ(test, 0x02, tag);
+       KUNIT_EXPECT_EQ(test, 0x0d, channel);
+       KUNIT_EXPECT_EQ(test, 0x0e, tcode);
+       KUNIT_EXPECT_EQ(test, 0x0c, sy);
+
+       serialize_isoc_header(&header, data_length, tag, channel, tcode, sy);
+
+       KUNIT_EXPECT_EQ(test, header, expected);
+}
 
 static struct kunit_case packet_serdes_test_cases[] = {
        KUNIT_CASE(test_async_header_write_quadlet_request),
@@ -526,6 +569,7 @@ static struct kunit_case packet_serdes_test_cases[] = {
        KUNIT_CASE(test_async_header_read_block_response),
        KUNIT_CASE(test_async_header_lock_request),
        KUNIT_CASE(test_async_header_lock_response),
+       KUNIT_CASE(test_isoc_header),
        {}
 };