1

firewire: ohci: add static inline functions to serialize/deserialize data of IT DMA

In 1394 OHCI specification, the format of data for IT DMA is different from
the format of isochronous packet in IEEE 1394 specification, in its spd and
srcBusID fields.

This commit adds some static inline functions to serialize/deserialize the
data of IT DMA.

Link: https://lore.kernel.org/r/20240802003606.109402-4-o-takashi@sakamocchi.jp
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
This commit is contained in:
Takashi Sakamoto 2024-08-02 09:36:05 +09:00
parent db7a8f5519
commit 1ce2a92b53
2 changed files with 116 additions and 0 deletions

View File

@ -73,10 +73,42 @@ static void test_at_data_serdes(struct kunit *test)
KUNIT_EXPECT_MEMEQ(test, quadlets, expected, sizeof(expected));
}
static void test_it_data_serdes(struct kunit *test)
{
static const __le32 expected[] = {
cpu_to_le32(0x000349a7),
cpu_to_le32(0x02300000),
};
__le32 quadlets[] = {0, 0};
unsigned int scode = ohci1394_it_data_get_speed(expected);
unsigned int tag = ohci1394_it_data_get_tag(expected);
unsigned int channel = ohci1394_it_data_get_channel(expected);
unsigned int tcode = ohci1394_it_data_get_tcode(expected);
unsigned int sync = ohci1394_it_data_get_sync(expected);
unsigned int data_length = ohci1394_it_data_get_data_length(expected);
KUNIT_EXPECT_EQ(test, 0x03, scode);
KUNIT_EXPECT_EQ(test, 0x01, tag);
KUNIT_EXPECT_EQ(test, 0x09, channel);
KUNIT_EXPECT_EQ(test, 0x0a, tcode);
KUNIT_EXPECT_EQ(test, 0x7, sync);
KUNIT_EXPECT_EQ(test, 0x0230, data_length);
ohci1394_it_data_set_speed(quadlets, scode);
ohci1394_it_data_set_tag(quadlets, tag);
ohci1394_it_data_set_channel(quadlets, channel);
ohci1394_it_data_set_tcode(quadlets, tcode);
ohci1394_it_data_set_sync(quadlets, sync);
ohci1394_it_data_set_data_length(quadlets, data_length);
KUNIT_EXPECT_MEMEQ(test, quadlets, expected, sizeof(expected));
}
static struct kunit_case ohci_serdes_test_cases[] = {
KUNIT_CASE(test_self_id_count_register_deserialization),
KUNIT_CASE(test_self_id_receive_buffer_deserialization),
KUNIT_CASE(test_at_data_serdes),
KUNIT_CASE(test_it_data_serdes),
{}
};

View File

@ -269,6 +269,90 @@ static inline void ohci1394_at_data_set_rcode(__le32 *data, unsigned int rcode)
data[1] |= cpu_to_le32((rcode << OHCI1394_AT_DATA_Q1_rCode_SHIFT) & OHCI1394_AT_DATA_Q1_rCode_MASK);
}
// Isochronous Transmit DMA.
//
// The content of first two quadlets of data for IT DMA is different from the header for IEEE 1394
// isochronous packet.
#define OHCI1394_IT_DATA_Q0_spd_MASK 0x00070000
#define OHCI1394_IT_DATA_Q0_spd_SHIFT 16
#define OHCI1394_IT_DATA_Q0_tag_MASK 0x0000c000
#define OHCI1394_IT_DATA_Q0_tag_SHIFT 14
#define OHCI1394_IT_DATA_Q0_chanNum_MASK 0x00003f00
#define OHCI1394_IT_DATA_Q0_chanNum_SHIFT 8
#define OHCI1394_IT_DATA_Q0_tcode_MASK 0x000000f0
#define OHCI1394_IT_DATA_Q0_tcode_SHIFT 4
#define OHCI1394_IT_DATA_Q0_sy_MASK 0x0000000f
#define OHCI1394_IT_DATA_Q0_sy_SHIFT 0
#define OHCI1394_IT_DATA_Q1_dataLength_MASK 0xffff0000
#define OHCI1394_IT_DATA_Q1_dataLength_SHIFT 16
static inline unsigned int ohci1394_it_data_get_speed(const __le32 *data)
{
return (le32_to_cpu(data[0]) & OHCI1394_IT_DATA_Q0_spd_MASK) >> OHCI1394_IT_DATA_Q0_spd_SHIFT;
}
static inline void ohci1394_it_data_set_speed(__le32 *data, unsigned int scode)
{
data[0] &= cpu_to_le32(~OHCI1394_IT_DATA_Q0_spd_MASK);
data[0] |= cpu_to_le32((scode << OHCI1394_IT_DATA_Q0_spd_SHIFT) & OHCI1394_IT_DATA_Q0_spd_MASK);
}
static inline unsigned int ohci1394_it_data_get_tag(const __le32 *data)
{
return (le32_to_cpu(data[0]) & OHCI1394_IT_DATA_Q0_tag_MASK) >> OHCI1394_IT_DATA_Q0_tag_SHIFT;
}
static inline void ohci1394_it_data_set_tag(__le32 *data, unsigned int tag)
{
data[0] &= cpu_to_le32(~OHCI1394_IT_DATA_Q0_tag_MASK);
data[0] |= cpu_to_le32((tag << OHCI1394_IT_DATA_Q0_tag_SHIFT) & OHCI1394_IT_DATA_Q0_tag_MASK);
}
static inline unsigned int ohci1394_it_data_get_channel(const __le32 *data)
{
return (le32_to_cpu(data[0]) & OHCI1394_IT_DATA_Q0_chanNum_MASK) >> OHCI1394_IT_DATA_Q0_chanNum_SHIFT;
}
static inline void ohci1394_it_data_set_channel(__le32 *data, unsigned int channel)
{
data[0] &= cpu_to_le32(~OHCI1394_IT_DATA_Q0_chanNum_MASK);
data[0] |= cpu_to_le32((channel << OHCI1394_IT_DATA_Q0_chanNum_SHIFT) & OHCI1394_IT_DATA_Q0_chanNum_MASK);
}
static inline unsigned int ohci1394_it_data_get_tcode(const __le32 *data)
{
return (le32_to_cpu(data[0]) & OHCI1394_IT_DATA_Q0_tcode_MASK) >> OHCI1394_IT_DATA_Q0_tcode_SHIFT;
}
static inline void ohci1394_it_data_set_tcode(__le32 *data, unsigned int tcode)
{
data[0] &= cpu_to_le32(~OHCI1394_IT_DATA_Q0_tcode_MASK);
data[0] |= cpu_to_le32((tcode << OHCI1394_IT_DATA_Q0_tcode_SHIFT) & OHCI1394_IT_DATA_Q0_tcode_MASK);
}
static inline unsigned int ohci1394_it_data_get_sync(const __le32 *data)
{
return (le32_to_cpu(data[0]) & OHCI1394_IT_DATA_Q0_sy_MASK) >> OHCI1394_IT_DATA_Q0_sy_SHIFT;
}
static inline void ohci1394_it_data_set_sync(__le32 *data, unsigned int sync)
{
data[0] &= cpu_to_le32(~OHCI1394_IT_DATA_Q0_sy_MASK);
data[0] |= cpu_to_le32((sync << OHCI1394_IT_DATA_Q0_sy_SHIFT) & OHCI1394_IT_DATA_Q0_sy_MASK);
}
static inline unsigned int ohci1394_it_data_get_data_length(const __le32 *data)
{
return (le32_to_cpu(data[1]) & OHCI1394_IT_DATA_Q1_dataLength_MASK) >> OHCI1394_IT_DATA_Q1_dataLength_SHIFT;
}
static inline void ohci1394_it_data_set_data_length(__le32 *data, unsigned int data_length)
{
data[1] &= cpu_to_le32(~OHCI1394_IT_DATA_Q1_dataLength_MASK);
data[1] |= cpu_to_le32((data_length << OHCI1394_IT_DATA_Q1_dataLength_SHIFT) & OHCI1394_IT_DATA_Q1_dataLength_MASK);
}
// Self-ID DMA.
#define OHCI1394_SelfIDCount_selfIDError_MASK 0x80000000