1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 1993-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 /******************************* DisplayPort *******************************\
25 *                                                                           *
26 * Module: dp_address.h                                                      *
27 *    Basic class for AUX Address                                            *
28 *                                                                           *
29 \***************************************************************************/
30 
31 #ifndef INCLUDED_DP_ADDRESS_H
32 #define INCLUDED_DP_ADDRESS_H
33 
34 #include "dp_internal.h"
35 
36 namespace DisplayPort
37 {
38     class Address
39     {
40     public:
41         enum
42         {
43             maxHops = 15,       // update DP_MAX_ADDRESS_HOPS when changed (in displayportCommon.h)
44             maxHopsHDCP = 7,
45             maxPortCount = 15
46         };
47 
Address()48         Address()
49         {
50             clear();
51         }
52 
Address(unsigned hop0)53         Address(unsigned hop0)
54         {
55             clear();
56             hop[hops++] = hop0;
57         }
58 
Address(unsigned hop0,unsigned hop1)59         Address(unsigned hop0, unsigned hop1)
60         {
61             clear();
62             hop[hops++] = hop0;
63             hop[hops++] = hop1;
64         }
65 
Address(const Address & other)66         Address(const Address & other)
67         {
68             clear();
69             for(unsigned i = 0; i < other.size(); i++)
70             {
71                 append(other[i]);
72             }
73         }
74 
clear()75         void clear()
76         {
77             hops = 0;
78             for (unsigned i = 0; i < maxHops; i++)
79             {
80                 hop[i] = 0;
81             }
82         }
83 
parent()84         Address parent() const
85         {
86             if (hops == 0)
87             {
88                 DP_ASSERT(hops != 0);
89                 return 0;
90             }
91             Address addr = *this;
92             addr.hops --;
93             return addr;
94         }
95 
tail()96         unsigned tail() const
97         {
98             if (hops == 0)
99             {
100                 DP_ASSERT(hops != 0);
101                 return 0;
102             }
103             return hop[hops-1];
104         }
105 
append(unsigned port)106         void append(unsigned port)
107         {
108             if (hops >= maxHops)
109             {
110                 DP_ASSERT(0);
111                 return;
112             }
113             hop[hops++] = port;
114         }
115 
prepend(unsigned port)116         void prepend(unsigned port)
117         {
118             if (hops >= maxHops)
119             {
120                 DP_ASSERT(0);
121                 return;
122             }
123             hops++;
124             for (unsigned i = hops - 1; i > 0; i--)
125                 hop[i] = hop[i-1];
126             hop[0] = port;
127         }
128 
pop()129         void pop()
130         {
131             if (hops == 0)
132             {
133                 DP_ASSERT(0);
134                 return;
135             }
136             hops--;
137         }
138 
139         // Just to keep clear copy
140         Address & operator = (const Address & other)
141         {
142             clear();
143             for(unsigned i = 0; i < other.size(); i++)
144             {
145                 append(other[i]);
146             }
147 
148             return *this;
149         }
150 
151         bool operator == (const Address & other) const
152         {
153             if (other.size() != size())
154                 return false;
155 
156             for (unsigned i = 0; i < hops; i++)
157                 if (other[i] != (*this)[i])
158                     return false;
159 
160             return true;
161         }
162 
163         //
164         //  Sort by size first, then "alphabetically" (lexicographical see wikipedia)
165         //
166         bool operator > (const Address & other) const
167         {
168             if (size() > other.size())
169                 return true;
170             else if (size() < other.size())
171                 return false;
172 
173             for (unsigned i = 0; i < hops; i++)
174             {
175                 if ((*this)[i] > other[i])
176                     return true;
177                 else if ((*this)[i] < other[i])
178                     return false;
179             }
180 
181             return false;
182         }
183 
184         //
185         //  Sort by size first, then "alphabetically" (lexicographical see wikipedia)
186         //
187         bool operator < (const Address & other) const
188         {
189             if (size() < other.size())
190                 return true;
191             else if (size() > other.size())
192                 return false;
193 
194             for (unsigned i = 0; i < hops; i++)
195             {
196                 if ((*this)[i] < other[i])
197                     return true;
198                 else if ((*this)[i] > other[i])
199                     return false;
200             }
201 
202             return false;
203         }
204 
205         bool operator >= (const Address & other) const
206         {
207             return !((*this) < other);
208         }
209 
210         bool operator <= (const Address & other) const
211         {
212             return !((*this) > other);
213         }
214 
215         bool operator != (const Address & other) const
216         {
217             return !((*this) == other);
218         }
219 
size()220         unsigned size() const
221         {
222             return hops;
223         }
224 
225         unsigned & operator [](unsigned index)
226         {
227             DP_ASSERT(index < hops);
228             return hop[index];
229         }
230 
231         const unsigned & operator [](unsigned index) const
232         {
233             DP_ASSERT(index < hops);
234             return hop[index];
235         }
236 
under(const Address & root)237         bool under(const Address & root) const
238         {
239             if (size() < root.size())
240                 return false;
241 
242             for (unsigned i = 0; i < root.size(); i++)
243                 if ((*this)[i] != root[i])
244                     return false;
245 
246             return true;
247         }
248 
249         typedef char StringBuffer[maxHops*3+1];
250         char * toString(StringBuffer & buffer, bool removeLeadingZero = false) const
251         {
252             char * p = &buffer[0];
253             int hopsWritten = 0;
254             for (unsigned i = 0; i < hops; i++)
255             {
256                 if (i == 0 && hop[0] == 0 && removeLeadingZero)
257                     continue;
258                 if (hopsWritten > 0)
259                     *p++ = '.';
260                 if (hop[i] >= 10)
261                     *p++ = (char)(hop[i] / 10 +'0');
262                 *p++ = (char)(hop[i] % 10 + '0');
263                 hopsWritten++;
264             }
265 
266             *p++= 0;
267             return (char *)&buffer[0];
268         }
269 
270         // Large enough to fit 4 hops into every NvU32
271         typedef NvU32 NvU32Buffer[(maxHops-1)/4+1 < 4 ? 4 : (maxHops-1)/4+1];
toNvU32Buffer(NvU32Buffer & buffer)272         NvU32 * toNvU32Buffer(NvU32Buffer & buffer) const
273         {
274             for (unsigned i = 0; i < hops; i++)
275             {
276                 buffer[i/4] |= ((NvU8) hop[i]) << (i % 4) * 8;
277             }
278 
279             return (NvU32 *)&buffer[0];
280         }
281 
282     private:
283         unsigned hop[maxHops];
284         unsigned hops;
285     };
286 }
287 
288 #endif //INCLUDED_DP_ADDRESS_H
289