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