Linux Audio

Check our new training course

Embedded Linux training

Mar 10-20, 2025, special US time zones
Register
Loading...
Note: File does not exist in v6.2.
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2//
  3// phy-packet-definitions.h - The definitions of phy packet for IEEE 1394.
  4//
  5// Copyright (c) 2024 Takashi Sakamoto
  6
  7#ifndef _FIREWIRE_PHY_PACKET_DEFINITIONS_H
  8#define _FIREWIRE_PHY_PACKET_DEFINITIONS_H
  9
 10#define PACKET_IDENTIFIER_MASK				0xc0000000
 11#define PACKET_IDENTIFIER_SHIFT				30
 12
 13static inline unsigned int phy_packet_get_packet_identifier(u32 quadlet)
 14{
 15	return (quadlet & PACKET_IDENTIFIER_MASK) >> PACKET_IDENTIFIER_SHIFT;
 16}
 17
 18static inline void phy_packet_set_packet_identifier(u32 *quadlet, unsigned int packet_identifier)
 19{
 20	*quadlet &= ~PACKET_IDENTIFIER_MASK;
 21	*quadlet |= (packet_identifier << PACKET_IDENTIFIER_SHIFT) & PACKET_IDENTIFIER_MASK;
 22}
 23
 24#define PHY_PACKET_PACKET_IDENTIFIER_PHY_CONFIG		0
 25
 26#define PHY_CONFIG_ROOT_ID_MASK				0x3f000000
 27#define PHY_CONFIG_ROOT_ID_SHIFT			24
 28#define PHY_CONFIG_FORCE_ROOT_NODE_MASK			0x00800000
 29#define PHY_CONFIG_FORCE_ROOT_NODE_SHIFT		23
 30#define PHY_CONFIG_GAP_COUNT_OPTIMIZATION_MASK		0x00400000
 31#define PHY_CONFIG_GAP_COUNT_OPTIMIZATION_SHIFT		22
 32#define PHY_CONFIG_GAP_COUNT_MASK			0x003f0000
 33#define PHY_CONFIG_GAP_COUNT_SHIFT			16
 34
 35static inline unsigned int phy_packet_phy_config_get_root_id(u32 quadlet)
 36{
 37	return (quadlet & PHY_CONFIG_ROOT_ID_MASK) >> PHY_CONFIG_ROOT_ID_SHIFT;
 38}
 39
 40static inline void phy_packet_phy_config_set_root_id(u32 *quadlet, unsigned int root_id)
 41{
 42	*quadlet &= ~PHY_CONFIG_ROOT_ID_MASK;
 43	*quadlet |= (root_id << PHY_CONFIG_ROOT_ID_SHIFT) & PHY_CONFIG_ROOT_ID_MASK;
 44}
 45
 46static inline bool phy_packet_phy_config_get_force_root_node(u32 quadlet)
 47{
 48	return (quadlet & PHY_CONFIG_FORCE_ROOT_NODE_MASK) >> PHY_CONFIG_FORCE_ROOT_NODE_SHIFT;
 49}
 50
 51static inline void phy_packet_phy_config_set_force_root_node(u32 *quadlet, bool has_force_root_node)
 52{
 53	*quadlet &= ~PHY_CONFIG_FORCE_ROOT_NODE_MASK;
 54	*quadlet |= (has_force_root_node << PHY_CONFIG_FORCE_ROOT_NODE_SHIFT) & PHY_CONFIG_FORCE_ROOT_NODE_MASK;
 55}
 56
 57static inline bool phy_packet_phy_config_get_gap_count_optimization(u32 quadlet)
 58{
 59	return (quadlet & PHY_CONFIG_GAP_COUNT_OPTIMIZATION_MASK) >> PHY_CONFIG_GAP_COUNT_OPTIMIZATION_SHIFT;
 60}
 61
 62static inline void phy_packet_phy_config_set_gap_count_optimization(u32 *quadlet, bool has_gap_count_optimization)
 63{
 64	*quadlet &= ~PHY_CONFIG_GAP_COUNT_OPTIMIZATION_MASK;
 65	*quadlet |= (has_gap_count_optimization << PHY_CONFIG_GAP_COUNT_OPTIMIZATION_SHIFT) & PHY_CONFIG_GAP_COUNT_OPTIMIZATION_MASK;
 66}
 67
 68static inline unsigned int phy_packet_phy_config_get_gap_count(u32 quadlet)
 69{
 70	return (quadlet & PHY_CONFIG_GAP_COUNT_MASK) >> PHY_CONFIG_GAP_COUNT_SHIFT;
 71}
 72
 73static inline void phy_packet_phy_config_set_gap_count(u32 *quadlet, unsigned int gap_count)
 74{
 75	*quadlet &= ~PHY_CONFIG_GAP_COUNT_MASK;
 76	*quadlet |= (gap_count << PHY_CONFIG_GAP_COUNT_SHIFT) & PHY_CONFIG_GAP_COUNT_MASK;
 77}
 78
 79#define PHY_PACKET_PACKET_IDENTIFIER_SELF_ID		2
 80
 81#define SELF_ID_PHY_ID_MASK				0x3f000000
 82#define SELF_ID_PHY_ID_SHIFT				24
 83#define SELF_ID_EXTENDED_MASK				0x00800000
 84#define SELF_ID_EXTENDED_SHIFT				23
 85#define SELF_ID_MORE_PACKETS_MASK			0x00000001
 86#define SELF_ID_MORE_PACKETS_SHIFT			0
 87
 88#define SELF_ID_ZERO_LINK_ACTIVE_MASK			0x00400000
 89#define SELF_ID_ZERO_LINK_ACTIVE_SHIFT			22
 90#define SELF_ID_ZERO_GAP_COUNT_MASK			0x003f0000
 91#define SELF_ID_ZERO_GAP_COUNT_SHIFT			16
 92#define SELF_ID_ZERO_SCODE_MASK				0x0000c000
 93#define SELF_ID_ZERO_SCODE_SHIFT			14
 94#define SELF_ID_ZERO_CONTENDER_MASK			0x00000800
 95#define SELF_ID_ZERO_CONTENDER_SHIFT			11
 96#define SELF_ID_ZERO_POWER_CLASS_MASK			0x00000700
 97#define SELF_ID_ZERO_POWER_CLASS_SHIFT			8
 98#define SELF_ID_ZERO_INITIATED_RESET_MASK		0x00000002
 99#define SELF_ID_ZERO_INITIATED_RESET_SHIFT		1
100
101#define SELF_ID_EXTENDED_SEQUENCE_MASK			0x00700000
102#define SELF_ID_EXTENDED_SEQUENCE_SHIFT			20
103
104#define SELF_ID_PORT_STATUS_MASK			0x3
105
106#define SELF_ID_SEQUENCE_MAXIMUM_QUADLET_COUNT		4
107
108static inline unsigned int phy_packet_self_id_get_phy_id(u32 quadlet)
109{
110	return (quadlet & SELF_ID_PHY_ID_MASK)  >> SELF_ID_PHY_ID_SHIFT;
111}
112
113static inline void phy_packet_self_id_set_phy_id(u32 *quadlet, unsigned int phy_id)
114{
115	*quadlet &= ~SELF_ID_PHY_ID_MASK;
116	*quadlet |= (phy_id << SELF_ID_PHY_ID_SHIFT) & SELF_ID_PHY_ID_MASK;
117}
118
119static inline bool phy_packet_self_id_get_extended(u32 quadlet)
120{
121	return (quadlet & SELF_ID_EXTENDED_MASK) >> SELF_ID_EXTENDED_SHIFT;
122}
123
124static inline void phy_packet_self_id_set_extended(u32 *quadlet, bool extended)
125{
126	*quadlet &= ~SELF_ID_EXTENDED_MASK;
127	*quadlet |= (extended << SELF_ID_EXTENDED_SHIFT) & SELF_ID_EXTENDED_MASK;
128}
129
130static inline bool phy_packet_self_id_zero_get_link_active(u32 quadlet)
131{
132	return (quadlet & SELF_ID_ZERO_LINK_ACTIVE_MASK) >> SELF_ID_ZERO_LINK_ACTIVE_SHIFT;
133}
134
135static inline void phy_packet_self_id_zero_set_link_active(u32 *quadlet, bool is_active)
136{
137	*quadlet &= ~SELF_ID_ZERO_LINK_ACTIVE_MASK;
138	*quadlet |= (is_active << SELF_ID_ZERO_LINK_ACTIVE_SHIFT) & SELF_ID_ZERO_LINK_ACTIVE_MASK;
139}
140
141static inline unsigned int phy_packet_self_id_zero_get_gap_count(u32 quadlet)
142{
143	return (quadlet & SELF_ID_ZERO_GAP_COUNT_MASK) >> SELF_ID_ZERO_GAP_COUNT_SHIFT;
144}
145
146static inline void phy_packet_self_id_zero_set_gap_count(u32 *quadlet, unsigned int gap_count)
147{
148	*quadlet &= ~SELF_ID_ZERO_GAP_COUNT_MASK;
149	*quadlet |= (gap_count << SELF_ID_ZERO_GAP_COUNT_SHIFT) & SELF_ID_ZERO_GAP_COUNT_MASK;
150}
151
152static inline unsigned int phy_packet_self_id_zero_get_scode(u32 quadlet)
153{
154	return (quadlet & SELF_ID_ZERO_SCODE_MASK) >> SELF_ID_ZERO_SCODE_SHIFT;
155}
156
157static inline void phy_packet_self_id_zero_set_scode(u32 *quadlet, unsigned int speed)
158{
159	*quadlet &= ~SELF_ID_ZERO_SCODE_MASK;
160	*quadlet |= (speed << SELF_ID_ZERO_SCODE_SHIFT) & SELF_ID_ZERO_SCODE_MASK;
161}
162
163static inline bool phy_packet_self_id_zero_get_contender(u32 quadlet)
164{
165	return (quadlet & SELF_ID_ZERO_CONTENDER_MASK) >> SELF_ID_ZERO_CONTENDER_SHIFT;
166}
167
168static inline void phy_packet_self_id_zero_set_contender(u32 *quadlet, bool is_contender)
169{
170	*quadlet &= ~SELF_ID_ZERO_CONTENDER_MASK;
171	*quadlet |= (is_contender << SELF_ID_ZERO_CONTENDER_SHIFT) & SELF_ID_ZERO_CONTENDER_MASK;
172}
173
174static inline unsigned int phy_packet_self_id_zero_get_power_class(u32 quadlet)
175{
176	return (quadlet & SELF_ID_ZERO_POWER_CLASS_MASK) >> SELF_ID_ZERO_POWER_CLASS_SHIFT;
177}
178
179static inline void phy_packet_self_id_zero_set_power_class(u32 *quadlet, unsigned int power_class)
180{
181	*quadlet &= ~SELF_ID_ZERO_POWER_CLASS_MASK;
182	*quadlet |= (power_class << SELF_ID_ZERO_POWER_CLASS_SHIFT) & SELF_ID_ZERO_POWER_CLASS_MASK;
183}
184
185static inline bool phy_packet_self_id_zero_get_initiated_reset(u32 quadlet)
186{
187	return (quadlet & SELF_ID_ZERO_INITIATED_RESET_MASK) >> SELF_ID_ZERO_INITIATED_RESET_SHIFT;
188}
189
190static inline void phy_packet_self_id_zero_set_initiated_reset(u32 *quadlet, bool is_initiated_reset)
191{
192	*quadlet &= ~SELF_ID_ZERO_INITIATED_RESET_MASK;
193	*quadlet |= (is_initiated_reset << SELF_ID_ZERO_INITIATED_RESET_SHIFT) & SELF_ID_ZERO_INITIATED_RESET_MASK;
194}
195
196static inline bool phy_packet_self_id_get_more_packets(u32 quadlet)
197{
198	return (quadlet & SELF_ID_MORE_PACKETS_MASK) >> SELF_ID_MORE_PACKETS_SHIFT;
199}
200
201static inline void phy_packet_self_id_set_more_packets(u32 *quadlet, bool is_more_packets)
202{
203	*quadlet &= ~SELF_ID_MORE_PACKETS_MASK;
204	*quadlet |= (is_more_packets << SELF_ID_MORE_PACKETS_SHIFT) & SELF_ID_MORE_PACKETS_MASK;
205}
206
207static inline unsigned int phy_packet_self_id_extended_get_sequence(u32 quadlet)
208{
209	return (quadlet & SELF_ID_EXTENDED_SEQUENCE_MASK) >> SELF_ID_EXTENDED_SEQUENCE_SHIFT;
210}
211
212static inline void phy_packet_self_id_extended_set_sequence(u32 *quadlet, unsigned int sequence)
213{
214	*quadlet &= ~SELF_ID_EXTENDED_SEQUENCE_MASK;
215	*quadlet |= (sequence << SELF_ID_EXTENDED_SHIFT) & SELF_ID_EXTENDED_SEQUENCE_MASK;
216}
217
218struct self_id_sequence_enumerator {
219	const u32 *cursor;
220	unsigned int quadlet_count;
221};
222
223static inline const u32 *self_id_sequence_enumerator_next(
224		struct self_id_sequence_enumerator *enumerator, unsigned int *quadlet_count)
225{
226	const u32 *self_id_sequence, *cursor;
227	u32 quadlet;
228	unsigned int count;
229	unsigned int sequence;
230
231	if (enumerator->cursor == NULL || enumerator->quadlet_count == 0)
232		return ERR_PTR(-ENODATA);
233	cursor = enumerator->cursor;
234	count = 1;
235
236	quadlet = *cursor;
237	sequence = 0;
238	while (phy_packet_self_id_get_more_packets(quadlet)) {
239		if (count >= enumerator->quadlet_count ||
240		    count >= SELF_ID_SEQUENCE_MAXIMUM_QUADLET_COUNT)
241			return ERR_PTR(-EPROTO);
242		++cursor;
243		++count;
244		quadlet = *cursor;
245
246		if (!phy_packet_self_id_get_extended(quadlet) ||
247		    sequence != phy_packet_self_id_extended_get_sequence(quadlet))
248			return ERR_PTR(-EPROTO);
249		++sequence;
250	}
251
252	*quadlet_count = count;
253	self_id_sequence = enumerator->cursor;
254
255	enumerator->cursor += count;
256	enumerator->quadlet_count -= count;
257
258	return self_id_sequence;
259}
260
261enum phy_packet_self_id_port_status {
262	PHY_PACKET_SELF_ID_PORT_STATUS_NONE = 0,
263	PHY_PACKET_SELF_ID_PORT_STATUS_NCONN = 1,
264	PHY_PACKET_SELF_ID_PORT_STATUS_PARENT = 2,
265	PHY_PACKET_SELF_ID_PORT_STATUS_CHILD = 3,
266};
267
268static inline unsigned int self_id_sequence_get_port_capacity(unsigned int quadlet_count)
269{
270	return quadlet_count * 8 - 5;
271}
272
273static inline enum phy_packet_self_id_port_status self_id_sequence_get_port_status(
274		const u32 *self_id_sequence, unsigned int quadlet_count, unsigned int port_index)
275{
276	unsigned int index, shift;
277
278	index = (port_index + 5) / 8;
279	shift = 16 - ((port_index + 5) % 8) * 2;
280
281	if (index < quadlet_count && index < SELF_ID_SEQUENCE_MAXIMUM_QUADLET_COUNT)
282		return (self_id_sequence[index] >> shift) & SELF_ID_PORT_STATUS_MASK;
283
284	return PHY_PACKET_SELF_ID_PORT_STATUS_NONE;
285}
286
287static inline void self_id_sequence_set_port_status(u32 *self_id_sequence, unsigned int quadlet_count,
288						    unsigned int port_index,
289						    enum phy_packet_self_id_port_status status)
290{
291	unsigned int index, shift;
292
293	index = (port_index + 5) / 8;
294	shift = 16 - ((port_index + 5) % 8) * 2;
295
296	if (index < quadlet_count) {
297		self_id_sequence[index] &= ~(SELF_ID_PORT_STATUS_MASK << shift);
298		self_id_sequence[index] |= status << shift;
299	}
300}
301
302#endif // _FIREWIRE_PHY_PACKET_DEFINITIONS_H