1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** NetX Component                                                        */
17 /**                                                                       */
18 /**   Packet Pool Management (Packet)                                     */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 #define NX_SOURCE_CODE
24 
25 
26 /* Include necessary system files.  */
27 
28 #include "nx_api.h"
29 #include "nx_packet.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _nx_packet_pool_create                              PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Yuxin Zhou, Microsoft Corporation                                   */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function creates a pool of fixed-size packets within the       */
45 /*    specified memory area.                                              */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    pool_ptr                              Packet Pool control block     */
50 /*    name_ptr                              Packet Pool string pointer    */
51 /*    payload_size                          Size of packet payload        */
52 /*    pool_start                            Starting address of pool      */
53 /*    pool_size                             Number of bytes in pool       */
54 /*                                                                        */
55 /*  OUTPUT                                                                */
56 /*                                                                        */
57 /*    status                                Return status                 */
58 /*                                                                        */
59 /*  CALLS                                                                 */
60 /*                                                                        */
61 /*    None                                                                */
62 /*                                                                        */
63 /*  CALLED BY                                                             */
64 /*                                                                        */
65 /*    Application Code                                                    */
66 /*                                                                        */
67 /*  RELEASE HISTORY                                                       */
68 /*                                                                        */
69 /*    DATE              NAME                      DESCRIPTION             */
70 /*                                                                        */
71 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
72 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
73 /*                                            resulting in version 6.1    */
74 /*                                                                        */
75 /**************************************************************************/
_nx_packet_pool_create(NX_PACKET_POOL * pool_ptr,CHAR * name_ptr,ULONG payload_size,VOID * pool_start,ULONG pool_size)76 UINT  _nx_packet_pool_create(NX_PACKET_POOL *pool_ptr, CHAR *name_ptr, ULONG payload_size,
77                              VOID *pool_start, ULONG pool_size)
78 {
79 
80 TX_INTERRUPT_SAVE_AREA
81 
82 NX_PACKET_POOL *tail_ptr;              /* Working packet pool pointer */
83 ULONG           packets;               /* Number of packets in pool   */
84 ULONG           original_payload_size; /* Original payload size       */
85 ULONG           header_size;           /* Rounded header size         */
86 CHAR           *packet_ptr;            /* Working packet pointer      */
87 CHAR           *next_packet_ptr;       /* Next packet pointer         */
88 CHAR           *end_of_pool;           /* End of pool area            */
89 CHAR           *payload_address;       /* Address of the first payload*/
90 VOID           *rounded_pool_start;    /* Rounded stating address     */
91 
92 
93     /* Save the original payload size.  */
94     original_payload_size =  payload_size;
95 
96     /* Align the starting address to four bytes. */
97     /*lint -e{923} suppress cast between ULONG and pointer.  */
98     rounded_pool_start = (VOID *)((((ALIGN_TYPE)pool_start + NX_PACKET_ALIGNMENT  - 1) / NX_PACKET_ALIGNMENT) * NX_PACKET_ALIGNMENT);
99 
100     /* Round the pool size down to something that is evenly divisible by alignment.  */
101     /*lint -e{923} suppress cast between ULONG and pointer.  */
102     pool_size = (ULONG)(((pool_size - ((ALIGN_TYPE)rounded_pool_start - (ALIGN_TYPE)pool_start)) / NX_PACKET_ALIGNMENT) * NX_PACKET_ALIGNMENT);
103 
104     /* Set the pool starting address. */
105     pool_start = rounded_pool_start;
106 
107     /* Calculate the address of payload. */
108     /*lint -e{923} suppress cast between ULONG and pointer.  */
109     payload_address = (CHAR *)((ALIGN_TYPE)rounded_pool_start + sizeof(NX_PACKET));
110 
111     /* Align the address of payload. */
112     /*lint -e{923} suppress cast between ULONG and pointer.  */
113     payload_address = (CHAR *)((((ALIGN_TYPE)payload_address + NX_PACKET_ALIGNMENT  - 1) / NX_PACKET_ALIGNMENT) * NX_PACKET_ALIGNMENT);
114 
115     /* Calculate the header size. */
116     /*lint -e{923} suppress cast between ULONG and pointer.  */
117     header_size = (ULONG)((ALIGN_TYPE)payload_address - (ALIGN_TYPE)rounded_pool_start);
118 
119     /* Round the packet size up to something that helps guarantee proper alignment for header and payload.  */
120     payload_size = (ULONG)(((header_size + payload_size + NX_PACKET_ALIGNMENT  - 1) / NX_PACKET_ALIGNMENT) * NX_PACKET_ALIGNMENT - header_size);
121 
122     /* Clear pool fields. */
123     memset(pool_ptr, 0, sizeof(NX_PACKET_POOL));
124 
125     /* Setup the basic packet pool fields.  */
126     pool_ptr -> nx_packet_pool_name =             name_ptr;
127     pool_ptr -> nx_packet_pool_suspension_list =  TX_NULL;
128     pool_ptr -> nx_packet_pool_suspended_count =  0;
129     pool_ptr -> nx_packet_pool_start =            (CHAR *)pool_start;
130     pool_ptr -> nx_packet_pool_size =             pool_size;
131     pool_ptr -> nx_packet_pool_payload_size =     original_payload_size;
132 
133     /* Calculate the end of the pool's memory area.  */
134     end_of_pool =  ((CHAR *)pool_start) + pool_size;
135 
136     /* Walk through the pool area, setting up the available packet list.  */
137     packets =            0;
138     packet_ptr =         (CHAR *)rounded_pool_start;
139     next_packet_ptr =    packet_ptr + (payload_size + header_size);
140 
141     /*lint -e{946} suppress pointer subtraction, since it is necessary. */
142     while (next_packet_ptr <= end_of_pool)
143     {
144 
145         /* Yes, we have another packet.  Increment the packet count.  */
146         packets++;
147 
148         /* Setup the link to the next packet.  */
149         /*lint -e{929} -e{740} -e{826} suppress cast of pointer to pointer, since it is necessary  */
150         ((NX_PACKET *)packet_ptr) -> nx_packet_queue_next =  (NX_PACKET *)next_packet_ptr;
151 
152         /* Remember that this packet pool is the owner.  */
153         /*lint -e{929} -e{740} -e{826} suppress cast of pointer to pointer, since it is necessary  */
154         ((NX_PACKET *)packet_ptr) -> nx_packet_pool_owner =  pool_ptr;
155 
156 #ifndef NX_DISABLE_PACKET_CHAIN
157         /* Clear the next packet pointer.  */
158         /*lint -e{929} -e{740} -e{826} suppress cast of pointer to pointer, since it is necessary  */
159         ((NX_PACKET *)packet_ptr) -> nx_packet_next =  (NX_PACKET *)NX_NULL;
160 #endif /* NX_DISABLE_PACKET_CHAIN */
161 
162         /* Mark the packet as free.  */
163         /*lint -e{929} -e{923} -e{740} -e{826} suppress cast of pointer to pointer, since it is necessary  */
164         ((NX_PACKET *)packet_ptr) -> nx_packet_union_next.nx_packet_tcp_queue_next =  (NX_PACKET *)NX_PACKET_FREE;
165 
166         /* Setup the packet data pointers.  */
167         /*lint -e{929} -e{928} -e{740} -e{826} suppress cast of pointer to pointer, since it is necessary  */
168         ((NX_PACKET *)packet_ptr) -> nx_packet_data_start =  (UCHAR *)(packet_ptr + header_size);
169 
170         /*lint -e{929} -e{928} -e{740} -e{826} suppress cast of pointer to pointer, since it is necessary  */
171         ((NX_PACKET *)packet_ptr) -> nx_packet_data_end =    (UCHAR *)(packet_ptr + header_size + original_payload_size);
172 
173         /* Add debug information. */
174         NX_PACKET_DEBUG(__FILE__, __LINE__, (NX_PACKET *)packet_ptr);
175 
176         /* Advance to the next packet.  */
177         packet_ptr =   next_packet_ptr;
178 
179         /* Update the next packet pointer.  */
180         next_packet_ptr =  packet_ptr + (payload_size + header_size);
181     }
182 
183     /* Backup to the last packet in the pool.  */
184     packet_ptr =  packet_ptr - (payload_size + header_size);
185 
186     /* Set the last packet's forward pointer to NULL.  */
187     /*lint -e{929} -e{740} -e{826} suppress cast of pointer to pointer, since it is necessary  */
188     ((NX_PACKET *)packet_ptr) -> nx_packet_queue_next =  NX_NULL;
189 
190     /* Save the remaining information in the pool control packet.  */
191     pool_ptr -> nx_packet_pool_available =  packets;
192     pool_ptr -> nx_packet_pool_total =      packets;
193 
194     /* Set the packet pool available list.  */
195     pool_ptr -> nx_packet_pool_available_list =  (NX_PACKET *)pool_start;
196 
197     /* If trace is enabled, register this object.  */
198     NX_TRACE_OBJECT_REGISTER(NX_TRACE_OBJECT_TYPE_PACKET_POOL, pool_ptr, name_ptr, payload_size, packets);
199 
200     /* If trace is enabled, insert this event into the trace buffer.  */
201     NX_TRACE_IN_LINE_INSERT(NX_TRACE_PACKET_POOL_CREATE, pool_ptr, payload_size, pool_start, pool_size, NX_TRACE_PACKET_EVENTS, 0, 0);
202 
203     /* Disable interrupts to place the packet pool on the created list.  */
204     TX_DISABLE
205 
206     /* Setup the packet pool ID to make it valid.  */
207     pool_ptr -> nx_packet_pool_id =  NX_PACKET_POOL_ID;
208 
209     /* Place the packet pool on the list of created packet pools.  First,
210        check for an empty list.  */
211     if (_nx_packet_pool_created_ptr)
212     {
213 
214         /* Pickup tail pointer.  */
215         tail_ptr =  _nx_packet_pool_created_ptr -> nx_packet_pool_created_previous;
216 
217         /* Place the new packet pool in the list.  */
218         _nx_packet_pool_created_ptr -> nx_packet_pool_created_previous =  pool_ptr;
219         tail_ptr -> nx_packet_pool_created_next =  pool_ptr;
220 
221         /* Setup this packet pool's created links.  */
222         pool_ptr -> nx_packet_pool_created_previous =  tail_ptr;
223         pool_ptr -> nx_packet_pool_created_next =      _nx_packet_pool_created_ptr;
224     }
225     else
226     {
227 
228         /* The created packet pool list is empty.  Add packet pool to empty list.  */
229         _nx_packet_pool_created_ptr =                  pool_ptr;
230         pool_ptr -> nx_packet_pool_created_next =      pool_ptr;
231         pool_ptr -> nx_packet_pool_created_previous =  pool_ptr;
232     }
233 
234     /* Increment the number of packet pools created.  */
235     _nx_packet_pool_created_count++;
236 
237     /* Restore interrupts.  */
238     TX_RESTORE
239 
240     /* Return NX_SUCCESS.  */
241     return(NX_SUCCESS);
242 }
243 
244