firewire: core: add common macro to serialize/deserialize isochronous packet header

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>
This commit is contained in:
Takashi Sakamoto 2024-04-28 16:13:45 +09:00
parent c5deb01849
commit 6503df3612
2 changed files with 110 additions and 0 deletions

View 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

View 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),
{}
};