1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: osl_Mbuf.h
4
5 Copyright (C)2009 Nintendo Co., Ltd. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Rev: 20396 $
14 *---------------------------------------------------------------------------*/
15
16 #ifndef NN_NET_OSL_OSL_MBUF_H_
17 #define NN_NET_OSL_OSL_MBUF_H_
18
19 #include <nn/os.h>
20 #include <nn/util/util_StaticAssert.h>
21 #include <string.h>
22
23 #define NN_NET_MAC_ADDRESS_SIZE 6
24
25 #define NN_NET_OSL_PAGE_SIZE NN_OS_MEMORY_PAGE_SIZE
26 /* Use pagesize(=4096) / n to avoid crossing page-boundary for DMA. */
27 #define NN_NET_OSL_MBUF_UNIT_SIZE (NN_OS_MEMORY_PAGE_SIZE / 2)
28 #define NN_NET_OSL_MBUF_HEADER_SIZE 40
29 #define NN_NET_OSL_MBUF_DATA_SIZE ((NN_NET_OSL_MBUF_UNIT_SIZE) - (NN_NET_OSL_MBUF_HEADER_SIZE))
30 #define NN_NET_OSL_MBUF_DATA_MIN_SIZE ((NN_NET_OSL_MBUF_UNIT_SIZE) - (NN_NET_OSL_MBUF_HEADER_SIZE))
31
32 #define NN_NET_OSL_M_DONTWAIT 0
33 #define NN_NET_OSL_M_WAIT 1
34 #define NN_NET_OSL_M_FREELIST 0x8000 /**< mbuf is in free list. (for debug */
35
36 #define NN_NET_OSL_M_BCAST 0x0200 /**< ブロードキャスト */
37 #define NN_NET_OSL_M_MCAST 0x0400 /**< マルチキャスト */
38 #define NN_NET_OSL_M_LOOPBACK 0x0800 /**< ループバック */
39
40 #define NN_NET_OSL_M_COPYALL 1000000000
41
42 #define NN_NET_OSL_MT_DATA 1 /**< Data frames */
43 #define NN_NET_OSL_MT_ATH_WMI 2 /**< Atheros WMI */
44
45 #define NN_NET_OSL_CAT_DRIVER 1
46 #define NN_NET_OSL_CAT_ATH NN_NET_OSL_CAT_DRIVER /**< Atheros driver category */
47
48 struct nnnetOslMbuf;
49 typedef struct nnnetOslMbuf nnnetOslMbuf;
50
51 /* mbuf data structure */
52 typedef struct nnnetOslMbuf
53 {
54 nnnetOslMbuf* m_next; /**< Next cluster */
55 nnnetOslMbuf* m_prev; /**< Previous cluster */
56 nnnetOslMbuf* m_nextpkt; /**< General purpose link */
57 s16 m_len; /**< Length of stored data */
58 s16 m_capacity;
59 s16 m_top; /**< Top offset of stored data */
60 u16 m_flags; /**< NN_NET_OSL_M_BCAST、NN_NET_OSL_M_MCAST、NN_NET_OSL_M_LOOPBACK の OR */
61 u16 m_protocol; /**< Protocol id, for socket and related module. */
62 u16 m_owner; /* Owner module. NN_NET_OSL_M_OWN_XXXX */
63 u16 m_name; /**< Category name tag. NN_NET_OSL_M_CAT_XXXX */
64 u16 m_pool;
65 u8 m_dst[NN_NET_MAC_ADDRESS_SIZE]; /**< Destination MAC address. */
66 u8 m_src[NN_NET_MAC_ADDRESS_SIZE]; /**< Source MAC address */
67 u8 m_data[NN_NET_OSL_MBUF_DATA_MIN_SIZE]; /**< Data buffer */
68 } nnnetOslMbuf;
69
70 /* mbuf in free pool */
71 typedef struct nnnetOslMbufFree
72 {
73 s32 m_nextFree; /**< Next free cluster index */
74 } nnnetOslMbufFree;
75
76 /* size validation */
77 NN_STATIC_ASSERT(sizeof(nnnetOslMbuf) == NN_NET_OSL_MBUF_UNIT_SIZE);
78 NN_STATIC_ASSERT(offsetof(nnnetOslMbuf, m_data) == NN_NET_OSL_MBUF_HEADER_SIZE);
79
80
81 // 以下、C 用宣言
82
83 #include <nn/util/detail/util_CLibImpl.h>
84
85 NN_EXTERN_C nnnetOslMbuf* nnnetOslMbuf_getm (u32 name, nnnetOslMbuf *orig, s32 len, s32 how, u8 type);
86 NN_EXTERN_C void nnnetOslMbuf_freem (nnnetOslMbuf* pMbuf_);
87 NN_EXTERN_C s32 nnnetOslMbuf_adj (nnnetOslMbuf* pMbuf_, s32 len);
88 NN_EXTERN_C s32 nnnetOslMbuf_append (nnnetOslMbuf* pMbuf_, s32 len, const u8 *cp);
89 NN_EXTERN_C nnnetOslMbuf* nnnetOslMbuf_prepend_a (nnnetOslMbuf* pMbuf_, s32 len, int how);
90 NN_EXTERN_C nnnetOslMbuf* nnnetOslMbuf_pullup (nnnetOslMbuf* pMbuf_, s32 len);
91 NN_EXTERN_C nnnetOslMbuf* nnnetOslMbuf_dup (nnnetOslMbuf* pMbuf_, int how);
92 NN_EXTERN_C s32 nnnetOslMbuf_copydata (const nnnetOslMbuf* pMbuf_, s32 offset, s32 len, u8 *buf);
93 NN_EXTERN_C s32 nnnetOslMbuf_copyback (nnnetOslMbuf* pMbuf_, s32 offset, s32 len, const u8 *buf);
94 NN_EXTERN_C s32 nnnetOslMbuf_cat (nnnetOslMbuf* pMbuf_, nnnetOslMbuf *n);
95 NN_EXTERN_C nnnetOslMbuf* nnnetOslMbuf_split (nnnetOslMbuf* pMbuf_, s32 len, int how);
96 NN_EXTERN_C s32 nnnetOslMbuf_length (nnnetOslMbuf* pMbuf_, nnnetOslMbuf **last);
97 NN_EXTERN_C s32 nnnetOslMbuf_apply (nnnetOslMbuf* pMbuf_, s32 offset, s32 len, s32 (* f)(void* arg, void* data, s32 len), void* arg);
98 NN_EXTERN_C void nnnetOslMbuf_dump (nnnetOslMbuf* pMbuf_);
99 NN_EXTERN_C bool nnnetOslMbuf_align (nnnetOslMbuf* pMbuf_, u8 align, s8 offset);
100
nnnetOslMbuf_leadingspace(const nnnetOslMbuf * pMbuf_)101 NN_EXTERN_C inline s32 nnnetOslMbuf_leadingspace(const nnnetOslMbuf* pMbuf_)
102 {
103 return pMbuf_->m_top;
104 }
105
nnnetOslMbuf_trailingspace(const nnnetOslMbuf * pMbuf_)106 NN_EXTERN_C inline s32 nnnetOslMbuf_trailingspace(const nnnetOslMbuf* pMbuf_)
107 {
108 return pMbuf_->m_capacity - (pMbuf_->m_top + pMbuf_->m_len);
109 }
110
nnnetOslMbuf_prepend(nnnetOslMbuf * pMbuf_,s32 len,int how)111 NN_EXTERN_C inline nnnetOslMbuf* nnnetOslMbuf_prepend(nnnetOslMbuf* pMbuf_, s32 len, int how)
112 {
113 if (pMbuf_->m_top >= len)
114 {
115 pMbuf_->m_top -= len;
116 pMbuf_->m_len += len;
117 return pMbuf_;
118 }
119 else
120 {
121 return nnnetOslMbuf_prepend_a(pMbuf_, len, how);
122 }
123 }
124
nnnetOslMbuf_tod(nnnetOslMbuf * pMbuf_)125 NN_EXTERN_C inline void* nnnetOslMbuf_tod (nnnetOslMbuf* pMbuf_)
126 {
127 //todo: Check consitency here.
128 return &(pMbuf_->m_data[pMbuf_->m_top]);
129 }
130
nnnetOslMbuf_setUserPointer(nnnetOslMbuf * pMbuf_,void * p)131 NN_EXTERN_C inline void nnnetOslMbuf_setUserPointer(nnnetOslMbuf* pMbuf_, void* p)
132 {
133 pMbuf_->m_nextpkt = (nnnetOslMbuf*)p;
134 }
135
nnnetOslMbuf_getUserPointer(nnnetOslMbuf * pMbuf_)136 NN_EXTERN_C inline void* nnnetOslMbuf_getUserPointer(nnnetOslMbuf* pMbuf_)
137 {
138 return pMbuf_->m_nextpkt;
139 }
140
nnnetOslMbuf_expand(nnnetOslMbuf * pMbuf_,s32 len,int how)141 NN_EXTERN_C inline bool nnnetOslMbuf_expand(nnnetOslMbuf* pMbuf_, s32 len, int how)
142 {
143 NN_UNUSED_VAR(how);
144 if (pMbuf_->m_top + pMbuf_->m_len + len > pMbuf_->m_capacity)
145 {
146 NN_LOG("nnnetOslMbuf_expand: out of capacity.(len = %d)\n", len);
147 return false;
148 }
149
150 pMbuf_->m_len += len;
151 return true;
152 }
153
nnnetOslMbuf_reserve(nnnetOslMbuf * pMbuf_,s32 len)154 NN_EXTERN_C inline void nnnetOslMbuf_reserve(nnnetOslMbuf* pMbuf_, s32 len)
155 {
156 NN_TASSERT_(pMbuf_->m_len == 0 && pMbuf_->m_top + len <= pMbuf_->m_capacity);
157 pMbuf_->m_top += len;
158 }
159
160 #ifdef __cplusplus
161
162 #include <new>
163
164 namespace nn { namespace net { namespace osl {
165
166 class MbufPool;
167
168 class Mbuf : public nnnetOslMbuf
169 {
170 public:
171 typedef s32 FreeIndex;
172 static const size_t HEADER_SIZE = NN_NET_OSL_MBUF_HEADER_SIZE;
173
Initialize(size_t unitSize,u16 poolId)174 void Initialize(size_t unitSize, u16 poolId)
175 {
176 std::memset(static_cast<nnnetOslMbuf*>(this), 0x00, HEADER_SIZE);
177 m_capacity = unitSize - HEADER_SIZE;
178 m_pool = poolId;
179 }
180
Mbuf(FreeIndex nextFree)181 Mbuf(FreeIndex nextFree)
182 {
183 Initialize(0, 0xffff);
184 reinterpret_cast<nnnetOslMbufFree*>(this)->m_nextFree = nextFree;
185 }
186
GetNextFreeIndexPtr(void)187 FreeIndex* GetNextFreeIndexPtr(void)
188 { return &reinterpret_cast<nnnetOslMbufFree*>(this)->m_nextFree; }
189
SetNextFreeIndex(FreeIndex freeIndex)190 void SetNextFreeIndex(FreeIndex freeIndex)
191 { reinterpret_cast<nnnetOslMbufFree*>(this)->m_nextFree = freeIndex; }
192
GetNextFreeIndex(void)193 FreeIndex GetNextFreeIndex(void) const
194 { return reinterpret_cast<const nnnetOslMbufFree*>(this)->m_nextFree; }
195
196 operator nnnetOslMbuf*()
197 { return reinterpret_cast<nnnetOslMbuf*>(this); }
198
GetNext(void)199 Mbuf* GetNext(void)
200 {
201 return reinterpret_cast<Mbuf*>(m_next);
202 }
203
GetNext(void)204 const Mbuf* GetNext(void) const
205 {
206 return reinterpret_cast<const Mbuf*>(m_next);
207 }
208
GetPrevious(void)209 Mbuf* GetPrevious(void)
210 {
211 return reinterpret_cast<Mbuf*>(m_prev);
212 }
213
GetPrevious(void)214 const Mbuf* GetPrevious(void) const
215 {
216 return reinterpret_cast<const Mbuf*>(m_prev);
217 }
218
SetNext(Mbuf * pMbuf)219 void SetNext(Mbuf* pMbuf)
220 {
221 m_next = reinterpret_cast<nnnetOslMbuf*>(pMbuf);
222 }
223
SetPrevious(Mbuf * pMbuf)224 void SetPrevious(Mbuf* pMbuf)
225 {
226 m_prev = reinterpret_cast<nnnetOslMbuf*>(pMbuf);
227 }
228
IsLinking(void)229 bool IsLinking(void) const
230 { return m_prev != NULL || m_next != NULL; }
231
Unlink(void)232 Mbuf* Unlink(void)
233 {
234 Mbuf* pNext = GetNext();
235 if (pNext)
236 {
237 SetNext(NULL);
238 pNext->SetPrevious(NULL);
239 return pNext;
240 }
241 else
242 {
243 return NULL;
244 }
245 }
246
247 void CopyFrom(const Mbuf* pSource);
248
249 Mbuf* GetTail(void);
250 const Mbuf* GetHead(void) const;
251
SetLengthTrimed(size_t len)252 size_t SetLengthTrimed(size_t len)
253 {
254 m_len = (len > m_capacity) ? m_capacity : len;
255 return m_len;
256 }
257
GetLength(void)258 size_t GetLength(void) const
259 {
260 NN_TASSERT_(m_len <= m_capacity);
261 return m_len;
262 }
263
SetLength(size_t len)264 size_t SetLength(size_t len)
265 {
266 NN_TASSERT_(len <= m_capacity);
267 return m_len = len;
268 }
269
Length(void)270 s16& Length(void)
271 { return m_len; }
272
GetFlags(void)273 u16 GetFlags(void) const
274 { return m_flags; }
275
SetFlags(u16 flags)276 void SetFlags(u16 flags)
277 { m_flags = flags; }
278
SetName(u32 name)279 void SetName(u32 name)
280 { m_name = name; }
281
GetName(void)282 u32 GetName(void) const
283 { return m_name; }
284
SetProtocol(u32 protocol)285 void SetProtocol(u32 protocol)
286 { m_protocol = protocol; }
287
GetProtocol(void)288 u32 GetProtocol(void) const
289 { return m_protocol; }
290
SetTop(s32 top)291 void SetTop(s32 top)
292 {
293 NN_TASSERT_(top < m_capacity);
294 m_top = top;
295 }
296
GetWritableLength(void)297 size_t GetWritableLength(void) const
298 {
299 NN_TASSERT_(m_top < m_capacity);
300 return m_capacity - m_top;
301 }
302
GetTop(void)303 s32 GetTop(void) const
304 {
305 return m_top;
306 }
307
GetLeadingSpace(void)308 s32 GetLeadingSpace(void) const
309 {
310 return m_top;
311 }
312
GetTrailingSpace(void)313 s32 GetTrailingSpace(void) const
314 {
315 return m_capacity - (m_top + m_len);
316 }
317
318 u8* GetTopPtr(s32 offset = 0)
319 {
320 NN_TASSERT_(m_top + offset < m_capacity);
321 return &m_data[m_top + offset];
322 }
323
324 const u8* GetTopPtr(s32 offset = 0) const
325 {
326 NN_TASSERT_(m_top + offset < m_capacity);
327 return &m_data[m_top + offset];
328 }
329
330 bool IsDataAligned(u8 align, s8 offset = 0) const
331 {
332 return IsAligned(reinterpret_cast<uptr>(GetTopPtr()), align, offset);
333 }
334
GetCapacity(void)335 s16 GetCapacity(void) const
336 {
337 return m_capacity;
338 }
339
GetUnitSize(void)340 s16 GetUnitSize(void) const
341 {
342 return m_capacity + HEADER_SIZE;
343 }
344
GetPoolId(void)345 u16 GetPoolId(void) const
346 {
347 return m_pool;
348 }
349
IsAligned(uptr address,u8 align,s8 offset)350 static bool IsAligned(uptr address, u8 align, s8 offset)
351 {
352 NN_TASSERT_(align != 0 && (align & (align - 1)) == 0);
353 return ((address + offset) & (align - 1)) == 0;
354 }
355
356 // TORIAEZU:
GetTotalLength(void)357 s32 GetTotalLength(void) const
358 {
359 const nnnetOslMbuf* p = reinterpret_cast<const nnnetOslMbuf*>(this);
360 return nnnetOslMbuf_length(const_cast<nnnetOslMbuf*>(p), NULL);
361 }
362
363 bool CopyChainTo(u8* pDst, s32 offset = 0, s32 len = NN_NET_OSL_M_COPYALL) const
364 {
365 return nnnetOslMbuf_copydata(reinterpret_cast<const nnnetOslMbuf*>(this), offset, len, pDst) == 0;
366 }
367
368 // C 版の速度も重視する
AlignData(u8 align,s8 offset)369 bool AlignData(u8 align, s8 offset)
370 {
371 return nnnetOslMbuf_align(reinterpret_cast<nnnetOslMbuf*>(this), align, offset);
372 }
373
Link(Mbuf * pNext)374 void Link(Mbuf* pNext)
375 {
376 SetNext(pNext);
377 pNext->SetPrevious(this);
378 }
379
380 void Dump(void) const;
381 void DumpAll(void) const;
382 void DumpChain(void) const;
383
384 protected:
385 };
386
387 }}} // namespace nn::net::osl
388
389 #endif // __cplusplus
390
391
392 #endif // NN_NET_OSL_OSL_MBUF_H_
393