]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
firewire: ohci: add static inline functions to serialize/deserialize data of IT DMA
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Fri, 2 Aug 2024 00:36:05 +0000 (09:36 +0900)
committerTakashi Sakamoto <o-takashi@sakamocchi.jp>
Fri, 2 Aug 2024 00:36:05 +0000 (09:36 +0900)
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>
drivers/firewire/ohci-serdes-test.c
drivers/firewire/ohci.h

index 5d48d53b493afab536b10eb353a020d12592e9ac..258f668619ef1c34b175a4dc44e9acecc33d1691 100644 (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),
        {}
 };
 
index a5501996137c037f4fd7de218182c288bef7f47c..218666cfe14a5ede98466ce787bbcc63ae83eefb 100644 (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