1// SPDX-License-Identifier: GPL-2.0-or-later
2//
3// packet-header-definitions.h - The definitions of header fields for IEEE 1394 packet.
4//
5// Copyright (c) 2024 Takashi Sakamoto
6
7#ifndef _FIREWIRE_PACKET_HEADER_DEFINITIONS_H
8#define _FIREWIRE_PACKET_HEADER_DEFINITIONS_H
9
10#define ASYNC_HEADER_QUADLET_COUNT		4
11
12#define ASYNC_HEADER_Q0_DESTINATION_SHIFT	16
13#define ASYNC_HEADER_Q0_DESTINATION_MASK	0xffff0000
14#define ASYNC_HEADER_Q0_TLABEL_SHIFT		10
15#define ASYNC_HEADER_Q0_TLABEL_MASK		0x0000fc00
16#define ASYNC_HEADER_Q0_RETRY_SHIFT		8
17#define ASYNC_HEADER_Q0_RETRY_MASK		0x00000300
18#define ASYNC_HEADER_Q0_TCODE_SHIFT		4
19#define ASYNC_HEADER_Q0_TCODE_MASK		0x000000f0
20#define ASYNC_HEADER_Q0_PRIORITY_SHIFT		0
21#define ASYNC_HEADER_Q0_PRIORITY_MASK		0x0000000f
22#define ASYNC_HEADER_Q1_SOURCE_SHIFT		16
23#define ASYNC_HEADER_Q1_SOURCE_MASK		0xffff0000
24#define ASYNC_HEADER_Q1_RCODE_SHIFT		12
25#define ASYNC_HEADER_Q1_RCODE_MASK		0x0000f000
26#define ASYNC_HEADER_Q1_RCODE_SHIFT		12
27#define ASYNC_HEADER_Q1_RCODE_MASK		0x0000f000
28#define ASYNC_HEADER_Q1_OFFSET_HIGH_SHIFT	0
29#define ASYNC_HEADER_Q1_OFFSET_HIGH_MASK	0x0000ffff
30#define ASYNC_HEADER_Q3_DATA_LENGTH_SHIFT	16
31#define ASYNC_HEADER_Q3_DATA_LENGTH_MASK	0xffff0000
32#define ASYNC_HEADER_Q3_EXTENDED_TCODE_SHIFT	0
33#define ASYNC_HEADER_Q3_EXTENDED_TCODE_MASK	0x0000ffff
34
35static inline unsigned int async_header_get_destination(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
36{
37	return (header[0] & ASYNC_HEADER_Q0_DESTINATION_MASK) >> ASYNC_HEADER_Q0_DESTINATION_SHIFT;
38}
39
40static inline unsigned int async_header_get_tlabel(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
41{
42	return (header[0] & ASYNC_HEADER_Q0_TLABEL_MASK) >> ASYNC_HEADER_Q0_TLABEL_SHIFT;
43}
44
45static inline unsigned int async_header_get_retry(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
46{
47	return (header[0] & ASYNC_HEADER_Q0_RETRY_MASK) >> ASYNC_HEADER_Q0_RETRY_SHIFT;
48}
49
50static inline unsigned int async_header_get_tcode(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
51{
52	return (header[0] & ASYNC_HEADER_Q0_TCODE_MASK) >> ASYNC_HEADER_Q0_TCODE_SHIFT;
53}
54
55static inline unsigned int async_header_get_priority(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
56{
57	return (header[0] & ASYNC_HEADER_Q0_PRIORITY_MASK) >> ASYNC_HEADER_Q0_PRIORITY_SHIFT;
58}
59
60static inline unsigned int async_header_get_source(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
61{
62	return (header[1] & ASYNC_HEADER_Q1_SOURCE_MASK) >> ASYNC_HEADER_Q1_SOURCE_SHIFT;
63}
64
65static inline unsigned int async_header_get_rcode(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
66{
67	return (header[1] & ASYNC_HEADER_Q1_RCODE_MASK) >> ASYNC_HEADER_Q1_RCODE_SHIFT;
68}
69
70static inline u64 async_header_get_offset(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
71{
72	u32 hi = (header[1] & ASYNC_HEADER_Q1_OFFSET_HIGH_MASK) >> ASYNC_HEADER_Q1_OFFSET_HIGH_SHIFT;
73	return (((u64)hi) << 32) | ((u64)header[2]);
74}
75
76static inline u32 async_header_get_quadlet_data(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
77{
78	return header[3];
79}
80
81static inline unsigned int async_header_get_data_length(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
82{
83	return (header[3] & ASYNC_HEADER_Q3_DATA_LENGTH_MASK) >> ASYNC_HEADER_Q3_DATA_LENGTH_SHIFT;
84}
85
86static inline unsigned int async_header_get_extended_tcode(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
87{
88	return (header[3] & ASYNC_HEADER_Q3_EXTENDED_TCODE_MASK) >> ASYNC_HEADER_Q3_EXTENDED_TCODE_SHIFT;
89}
90
91static inline void async_header_set_destination(u32 header[ASYNC_HEADER_QUADLET_COUNT],
92						unsigned int destination)
93{
94	header[0] &= ~ASYNC_HEADER_Q0_DESTINATION_MASK;
95	header[0] |= (((u32)destination) << ASYNC_HEADER_Q0_DESTINATION_SHIFT) & ASYNC_HEADER_Q0_DESTINATION_MASK;
96}
97
98static inline void async_header_set_tlabel(u32 header[ASYNC_HEADER_QUADLET_COUNT],
99					   unsigned int tlabel)
100{
101	header[0] &= ~ASYNC_HEADER_Q0_TLABEL_MASK;
102	header[0] |= (((u32)tlabel) << ASYNC_HEADER_Q0_TLABEL_SHIFT) & ASYNC_HEADER_Q0_TLABEL_MASK;
103}
104
105static inline void async_header_set_retry(u32 header[ASYNC_HEADER_QUADLET_COUNT],
106					  unsigned int retry)
107{
108	header[0] &= ~ASYNC_HEADER_Q0_RETRY_MASK;
109	header[0] |= (((u32)retry) << ASYNC_HEADER_Q0_RETRY_SHIFT) & ASYNC_HEADER_Q0_RETRY_MASK;
110}
111
112static inline void async_header_set_tcode(u32 header[ASYNC_HEADER_QUADLET_COUNT],
113					  unsigned int tcode)
114{
115	header[0] &= ~ASYNC_HEADER_Q0_TCODE_MASK;
116	header[0] |= (((u32)tcode) << ASYNC_HEADER_Q0_TCODE_SHIFT) & ASYNC_HEADER_Q0_TCODE_MASK;
117}
118
119static inline void async_header_set_priority(u32 header[ASYNC_HEADER_QUADLET_COUNT],
120					     unsigned int priority)
121{
122	header[0] &= ~ASYNC_HEADER_Q0_PRIORITY_MASK;
123	header[0] |= (((u32)priority) << ASYNC_HEADER_Q0_PRIORITY_SHIFT) & ASYNC_HEADER_Q0_PRIORITY_MASK;
124}
125
126
127static inline void async_header_set_source(u32 header[ASYNC_HEADER_QUADLET_COUNT],
128					   unsigned int source)
129{
130	header[1] &= ~ASYNC_HEADER_Q1_SOURCE_MASK;
131	header[1] |= (((u32)source) << ASYNC_HEADER_Q1_SOURCE_SHIFT) & ASYNC_HEADER_Q1_SOURCE_MASK;
132}
133
134static inline void async_header_set_rcode(u32 header[ASYNC_HEADER_QUADLET_COUNT],
135					  unsigned int rcode)
136{
137	header[1] &= ~ASYNC_HEADER_Q1_RCODE_MASK;
138	header[1] |= (((u32)rcode) << ASYNC_HEADER_Q1_RCODE_SHIFT) & ASYNC_HEADER_Q1_RCODE_MASK;
139}
140
141static inline void async_header_set_offset(u32 header[ASYNC_HEADER_QUADLET_COUNT], u64 offset)
142{
143	u32 hi = (u32)(offset >> 32);
144	header[1] &= ~ASYNC_HEADER_Q1_OFFSET_HIGH_MASK;
145	header[1] |= (hi << ASYNC_HEADER_Q1_OFFSET_HIGH_SHIFT) & ASYNC_HEADER_Q1_OFFSET_HIGH_MASK;
146	header[2] = (u32)(offset & 0x00000000ffffffff);
147}
148
149static inline void async_header_set_quadlet_data(u32 header[ASYNC_HEADER_QUADLET_COUNT], u32 quadlet_data)
150{
151	header[3] = quadlet_data;
152}
153
154static inline void async_header_set_data_length(u32 header[ASYNC_HEADER_QUADLET_COUNT],
155						unsigned int data_length)
156{
157	header[3] &= ~ASYNC_HEADER_Q3_DATA_LENGTH_MASK;
158	header[3] |= (((u32)data_length) << ASYNC_HEADER_Q3_DATA_LENGTH_SHIFT) & ASYNC_HEADER_Q3_DATA_LENGTH_MASK;
159}
160
161static inline void async_header_set_extended_tcode(u32 header[ASYNC_HEADER_QUADLET_COUNT],
162						   unsigned int extended_tcode)
163{
164	header[3] &= ~ASYNC_HEADER_Q3_EXTENDED_TCODE_MASK;
165	header[3] |= (((u32)extended_tcode) << ASYNC_HEADER_Q3_EXTENDED_TCODE_SHIFT) & ASYNC_HEADER_Q3_EXTENDED_TCODE_MASK;
166}
167
168#define ISOC_HEADER_DATA_LENGTH_SHIFT		16
169#define ISOC_HEADER_DATA_LENGTH_MASK		0xffff0000
170#define ISOC_HEADER_TAG_SHIFT			14
171#define ISOC_HEADER_TAG_MASK			0x0000c000
172#define ISOC_HEADER_CHANNEL_SHIFT		8
173#define ISOC_HEADER_CHANNEL_MASK		0x00003f00
174#define ISOC_HEADER_TCODE_SHIFT			4
175#define ISOC_HEADER_TCODE_MASK			0x000000f0
176#define ISOC_HEADER_SY_SHIFT			0
177#define ISOC_HEADER_SY_MASK			0x0000000f
178
179static inline unsigned int isoc_header_get_data_length(u32 header)
180{
181	return (header & ISOC_HEADER_DATA_LENGTH_MASK) >> ISOC_HEADER_DATA_LENGTH_SHIFT;
182}
183
184static inline unsigned int isoc_header_get_tag(u32 header)
185{
186	return (header & ISOC_HEADER_TAG_MASK) >> ISOC_HEADER_TAG_SHIFT;
187}
188
189static inline unsigned int isoc_header_get_channel(u32 header)
190{
191	return (header & ISOC_HEADER_CHANNEL_MASK) >> ISOC_HEADER_CHANNEL_SHIFT;
192}
193
194static inline unsigned int isoc_header_get_tcode(u32 header)
195{
196	return (header & ISOC_HEADER_TCODE_MASK) >> ISOC_HEADER_TCODE_SHIFT;
197}
198
199static inline unsigned int isoc_header_get_sy(u32 header)
200{
201	return (header & ISOC_HEADER_SY_MASK) >> ISOC_HEADER_SY_SHIFT;
202}
203
204static inline void isoc_header_set_data_length(u32 *header, unsigned int data_length)
205{
206	*header &= ~ISOC_HEADER_DATA_LENGTH_MASK;
207	*header |= (((u32)data_length) << ISOC_HEADER_DATA_LENGTH_SHIFT) & ISOC_HEADER_DATA_LENGTH_MASK;
208}
209
210static inline void isoc_header_set_tag(u32 *header, unsigned int tag)
211{
212	*header &= ~ISOC_HEADER_TAG_MASK;
213	*header |= (((u32)tag) << ISOC_HEADER_TAG_SHIFT) & ISOC_HEADER_TAG_MASK;
214}
215
216static inline void isoc_header_set_channel(u32 *header, unsigned int channel)
217{
218	*header &= ~ISOC_HEADER_CHANNEL_MASK;
219	*header |= (((u32)channel) << ISOC_HEADER_CHANNEL_SHIFT) & ISOC_HEADER_CHANNEL_MASK;
220}
221
222static inline void isoc_header_set_tcode(u32 *header, unsigned int tcode)
223{
224	*header &= ~ISOC_HEADER_TCODE_MASK;
225	*header |= (((u32)tcode) << ISOC_HEADER_TCODE_SHIFT) & ISOC_HEADER_TCODE_MASK;
226}
227
228static inline void isoc_header_set_sy(u32 *header, unsigned int sy)
229{
230	*header &= ~ISOC_HEADER_SY_MASK;
231	*header |= (((u32)sy) << ISOC_HEADER_SY_SHIFT) & ISOC_HEADER_SY_MASK;
232}
233
234#endif // _FIREWIRE_PACKET_HEADER_DEFINITIONS_H
235