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