]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/Network/IScsiDxe/IScsiTcp4Io.c
update function header
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / IScsiTcp4Io.c
... / ...
CommitLineData
1/** @file\r
2 The wrap of TCP/IP Socket interface.\r
3\r
4Copyright (c) 2004 - 2007, Intel Corporation.<BR>\r
5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "IScsiImpl.h"\r
16\r
17/**\r
18 The common notify function associated with various Tcp4Io events. \r
19\r
20 @param[in] Event The event signaled.\r
21 @param[in] Context The context.\r
22**/\r
23VOID\r
24EFIAPI\r
25Tcp4IoCommonNotify (\r
26 IN EFI_EVENT Event,\r
27 IN VOID *Context\r
28 )\r
29{\r
30 *((BOOLEAN *) Context) = TRUE;\r
31}\r
32\r
33/**\r
34 Create a TCP socket with the specified configuration data. \r
35\r
36 @param[in] Image The handle of the driver image.\r
37 @param[in] Controller The handle of the controller.\r
38 @param[in] ConfigData The Tcp4 configuration data.\r
39 @param[in] Tcp4Io The Tcp4Io.\r
40 \r
41 @retval EFI_SUCCESS The TCP socket is created and configured.\r
42 @retval Others Failed to create the TCP socket or configure it.\r
43**/\r
44EFI_STATUS\r
45Tcp4IoCreateSocket (\r
46 IN EFI_HANDLE Image,\r
47 IN EFI_HANDLE Controller,\r
48 IN TCP4_IO_CONFIG_DATA *ConfigData,\r
49 IN TCP4_IO *Tcp4Io\r
50 )\r
51{\r
52 EFI_STATUS Status;\r
53 EFI_TCP4_PROTOCOL *Tcp4;\r
54 EFI_TCP4_CONFIG_DATA Tcp4ConfigData;\r
55 EFI_TCP4_OPTION ControlOption;\r
56 EFI_TCP4_ACCESS_POINT *AccessPoint;\r
57\r
58 Tcp4Io->Handle = NULL;\r
59 Tcp4Io->ConnToken.CompletionToken.Event = NULL;\r
60 Tcp4Io->TxToken.CompletionToken.Event = NULL;\r
61 Tcp4Io->RxToken.CompletionToken.Event = NULL;\r
62 Tcp4Io->CloseToken.CompletionToken.Event = NULL;\r
63 Tcp4 = NULL;\r
64\r
65 //\r
66 // Create the TCP4 child instance and get the TCP4 protocol.\r
67 //\r
68 Status = NetLibCreateServiceChild (\r
69 Controller,\r
70 Image,\r
71 &gEfiTcp4ServiceBindingProtocolGuid,\r
72 &Tcp4Io->Handle\r
73 );\r
74 if (EFI_ERROR (Status)) {\r
75 return Status;\r
76 }\r
77\r
78 Status = gBS->OpenProtocol (\r
79 Tcp4Io->Handle,\r
80 &gEfiTcp4ProtocolGuid,\r
81 (VOID **)&Tcp4Io->Tcp4,\r
82 Image,\r
83 Controller,\r
84 EFI_OPEN_PROTOCOL_BY_DRIVER\r
85 );\r
86 if (EFI_ERROR (Status)) {\r
87 goto ON_ERROR;\r
88 }\r
89\r
90 Tcp4Io->Image = Image;\r
91 Tcp4Io->Controller = Controller;\r
92 Tcp4 = Tcp4Io->Tcp4;\r
93\r
94 //\r
95 // Set the configuration parameters.\r
96 //\r
97 ControlOption.ReceiveBufferSize = 0x200000;\r
98 ControlOption.SendBufferSize = 0x200000;\r
99 ControlOption.MaxSynBackLog = 0;\r
100 ControlOption.ConnectionTimeout = 0;\r
101 ControlOption.DataRetries = 6;\r
102 ControlOption.FinTimeout = 0;\r
103 ControlOption.TimeWaitTimeout = 0;\r
104 ControlOption.KeepAliveProbes = 4;\r
105 ControlOption.KeepAliveTime = 0;\r
106 ControlOption.KeepAliveInterval = 0;\r
107 ControlOption.EnableNagle = FALSE;\r
108 ControlOption.EnableTimeStamp = FALSE;\r
109 ControlOption.EnableWindowScaling = TRUE;\r
110 ControlOption.EnableSelectiveAck = FALSE;\r
111 ControlOption.EnablePathMtuDiscovery = FALSE;\r
112\r
113 Tcp4ConfigData.TypeOfService = 8;\r
114 Tcp4ConfigData.TimeToLive = 255;\r
115 Tcp4ConfigData.ControlOption = &ControlOption;\r
116\r
117 AccessPoint = &Tcp4ConfigData.AccessPoint;\r
118\r
119 AccessPoint->UseDefaultAddress = FALSE;\r
120 AccessPoint->StationPort = 0;\r
121 AccessPoint->RemotePort = ConfigData->RemotePort;\r
122 AccessPoint->ActiveFlag = TRUE;\r
123\r
124 CopyMem (&AccessPoint->StationAddress, &ConfigData->LocalIp, sizeof (EFI_IPv4_ADDRESS));\r
125 CopyMem (&AccessPoint->SubnetMask, &ConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
126 CopyMem (&AccessPoint->RemoteAddress, &ConfigData->RemoteIp, sizeof (EFI_IPv4_ADDRESS));\r
127\r
128 //\r
129 // Configure the TCP4 protocol.\r
130 //\r
131 Status = Tcp4->Configure (Tcp4, &Tcp4ConfigData);\r
132 if (EFI_ERROR (Status)) {\r
133 goto ON_ERROR;\r
134 }\r
135\r
136 if (!EFI_IP4_EQUAL (&ConfigData->Gateway, &mZeroIp4Addr)) {\r
137 //\r
138 // the gateway is not zero, add the default route by hand\r
139 //\r
140 Status = Tcp4->Routes (Tcp4, FALSE, &mZeroIp4Addr, &mZeroIp4Addr, &ConfigData->Gateway);\r
141 if (EFI_ERROR (Status)) {\r
142 goto ON_ERROR;\r
143 }\r
144 }\r
145 //\r
146 // Create events for variuos asynchronous operations.\r
147 //\r
148 Status = gBS->CreateEvent (\r
149 EVT_NOTIFY_SIGNAL,\r
150 TPL_NOTIFY,\r
151 Tcp4IoCommonNotify,\r
152 &Tcp4Io->IsConnDone,\r
153 &Tcp4Io->ConnToken.CompletionToken.Event\r
154 );\r
155 if (EFI_ERROR (Status)) {\r
156 goto ON_ERROR;\r
157 }\r
158\r
159 Status = gBS->CreateEvent (\r
160 EVT_NOTIFY_SIGNAL,\r
161 TPL_NOTIFY,\r
162 Tcp4IoCommonNotify,\r
163 &Tcp4Io->IsTxDone,\r
164 &Tcp4Io->TxToken.CompletionToken.Event\r
165 );\r
166 if (EFI_ERROR (Status)) {\r
167 goto ON_ERROR;\r
168 }\r
169\r
170 Status = gBS->CreateEvent (\r
171 EVT_NOTIFY_SIGNAL,\r
172 TPL_NOTIFY,\r
173 Tcp4IoCommonNotify,\r
174 &Tcp4Io->IsRxDone,\r
175 &Tcp4Io->RxToken.CompletionToken.Event\r
176 );\r
177 if (EFI_ERROR (Status)) {\r
178 goto ON_ERROR;\r
179 }\r
180\r
181 Status = gBS->CreateEvent (\r
182 EVT_NOTIFY_SIGNAL,\r
183 TPL_NOTIFY,\r
184 Tcp4IoCommonNotify,\r
185 &Tcp4Io->IsCloseDone,\r
186 &Tcp4Io->CloseToken.CompletionToken.Event\r
187 );\r
188 if (EFI_ERROR (Status)) {\r
189 goto ON_ERROR;\r
190 }\r
191\r
192 Tcp4Io->IsTxDone = FALSE;\r
193 Tcp4Io->IsRxDone = FALSE;\r
194\r
195 return EFI_SUCCESS;\r
196\r
197ON_ERROR:\r
198\r
199 if (Tcp4Io->RxToken.CompletionToken.Event != NULL) {\r
200 gBS->CloseEvent (Tcp4Io->RxToken.CompletionToken.Event);\r
201 }\r
202\r
203 if (Tcp4Io->TxToken.CompletionToken.Event != NULL) {\r
204 gBS->CloseEvent (Tcp4Io->TxToken.CompletionToken.Event);\r
205 }\r
206\r
207 if (Tcp4Io->ConnToken.CompletionToken.Event != NULL) {\r
208 gBS->CloseEvent (Tcp4Io->ConnToken.CompletionToken.Event);\r
209 }\r
210\r
211 if (Tcp4 != NULL) {\r
212 Tcp4->Configure (Tcp4, NULL);\r
213\r
214 gBS->CloseProtocol (\r
215 Tcp4Io->Handle,\r
216 &gEfiTcp4ProtocolGuid,\r
217 Image,\r
218 Controller\r
219 );\r
220 }\r
221\r
222 NetLibDestroyServiceChild (\r
223 Controller,\r
224 Image,\r
225 &gEfiTcp4ServiceBindingProtocolGuid,\r
226 Tcp4Io->Handle\r
227 );\r
228\r
229 return Status;\r
230}\r
231\r
232/**\r
233 Destroy the socket. \r
234\r
235 @param[in] Tcp4Io The Tcp4Io which wraps the socket to be destroyeds.\r
236**/\r
237VOID\r
238Tcp4IoDestroySocket (\r
239 IN TCP4_IO *Tcp4Io\r
240 )\r
241{\r
242 EFI_TCP4_PROTOCOL *Tcp4;\r
243\r
244 Tcp4 = Tcp4Io->Tcp4;\r
245\r
246 Tcp4->Configure (Tcp4, NULL);\r
247\r
248 gBS->CloseEvent (Tcp4Io->TxToken.CompletionToken.Event);\r
249 gBS->CloseEvent (Tcp4Io->RxToken.CompletionToken.Event);\r
250 gBS->CloseEvent (Tcp4Io->ConnToken.CompletionToken.Event);\r
251\r
252 gBS->CloseProtocol (\r
253 Tcp4Io->Handle,\r
254 &gEfiTcp4ProtocolGuid,\r
255 Tcp4Io->Image,\r
256 Tcp4Io->Controller\r
257 );\r
258\r
259 NetLibDestroyServiceChild (\r
260 Tcp4Io->Controller,\r
261 Tcp4Io->Image,\r
262 &gEfiTcp4ServiceBindingProtocolGuid,\r
263 Tcp4Io->Handle\r
264 );\r
265}\r
266\r
267/**\r
268 Connect to the other endpoint of the TCP socket.\r
269\r
270 @param[in] Tcp4Io The Tcp4Io wrapping the TCP socket.\r
271 @param[in] Timeout The time to wait for connection done.\r
272 \r
273 @retval EFI_SUCCESS Connect to the other endpoint of the TCP socket successfully.\r
274 @retval EFI_TIMEOUT Failed to connect to the other endpoint of the TCP socket in the specified time period.\r
275 @retval Others Some expected error happened.\r
276**/\r
277EFI_STATUS\r
278Tcp4IoConnect (\r
279 IN TCP4_IO *Tcp4Io,\r
280 IN EFI_EVENT Timeout\r
281 )\r
282{\r
283 EFI_TCP4_PROTOCOL *Tcp4;\r
284 EFI_STATUS Status;\r
285\r
286 Tcp4Io->IsConnDone = FALSE;\r
287 Tcp4 = Tcp4Io->Tcp4;\r
288 Status = Tcp4->Connect (Tcp4, &Tcp4Io->ConnToken);\r
289 if (EFI_ERROR (Status)) {\r
290 return Status;\r
291 }\r
292\r
293 while (!Tcp4Io->IsConnDone && EFI_ERROR (gBS->CheckEvent (Timeout))) {\r
294 Tcp4->Poll (Tcp4);\r
295 }\r
296\r
297 if (!Tcp4Io->IsConnDone) {\r
298 Status = EFI_TIMEOUT;\r
299 } else {\r
300 Status = Tcp4Io->ConnToken.CompletionToken.Status;\r
301 }\r
302\r
303 return Status;\r
304}\r
305\r
306/**\r
307 Reset the socket.\r
308\r
309 @param[in] Tcp4Io The Tcp4Io wrapping the TCP socket.\r
310**/\r
311VOID\r
312Tcp4IoReset (\r
313 IN TCP4_IO *Tcp4Io\r
314 )\r
315{\r
316 EFI_STATUS Status;\r
317 EFI_TCP4_PROTOCOL *Tcp4;\r
318\r
319 Tcp4Io->CloseToken.AbortOnClose = TRUE;\r
320 Tcp4Io->IsCloseDone = FALSE;\r
321\r
322 Tcp4 = Tcp4Io->Tcp4;\r
323 Status = Tcp4->Close (Tcp4, &Tcp4Io->CloseToken);\r
324 if (EFI_ERROR (Status)) {\r
325 return ;\r
326 }\r
327\r
328 while (!Tcp4Io->IsCloseDone) {\r
329 Tcp4->Poll (Tcp4);\r
330 }\r
331}\r
332\r
333/**\r
334 Transmit the Packet to the other endpoint of the socket.\r
335\r
336 @param[in] Tcp4Io The Tcp4Io wrapping the TCP socket.\r
337 @param[in] Packet The packet to transmit.\r
338 \r
339 @retval EFI_SUCCESS The packet is trasmitted.\r
340 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
341 @retval Others Some expected error happened.\r
342**/\r
343EFI_STATUS\r
344Tcp4IoTransmit (\r
345 IN TCP4_IO *Tcp4Io,\r
346 IN NET_BUF *Packet\r
347 )\r
348{\r
349 EFI_TCP4_TRANSMIT_DATA *TxData;\r
350 EFI_TCP4_PROTOCOL *Tcp4;\r
351 EFI_STATUS Status;\r
352\r
353 TxData = AllocatePool (sizeof (EFI_TCP4_TRANSMIT_DATA) + (Packet->BlockOpNum - 1) * sizeof (EFI_TCP4_FRAGMENT_DATA));\r
354 if (TxData == NULL) {\r
355 return EFI_OUT_OF_RESOURCES;\r
356 }\r
357\r
358 TxData->Push = TRUE;\r
359 TxData->Urgent = FALSE;\r
360 TxData->DataLength = Packet->TotalSize;\r
361\r
362 //\r
363 // Build the fragment table.\r
364 //\r
365 TxData->FragmentCount = Packet->BlockOpNum;\r
366 NetbufBuildExt (Packet, (NET_FRAGMENT *) &TxData->FragmentTable[0], &TxData->FragmentCount);\r
367\r
368 Tcp4Io->TxToken.Packet.TxData = TxData;\r
369\r
370 //\r
371 // Trasnmit the packet.\r
372 //\r
373 Tcp4 = Tcp4Io->Tcp4;\r
374 Status = Tcp4->Transmit (Tcp4, &Tcp4Io->TxToken);\r
375 if (EFI_ERROR (Status)) {\r
376 goto ON_EXIT;\r
377 }\r
378\r
379 while (!Tcp4Io->IsTxDone) {\r
380 Tcp4->Poll (Tcp4);\r
381 }\r
382\r
383 Tcp4Io->IsTxDone = FALSE;\r
384\r
385 Status = Tcp4Io->TxToken.CompletionToken.Status;\r
386\r
387ON_EXIT:\r
388\r
389 gBS->FreePool (TxData);\r
390\r
391 return Status;\r
392}\r
393\r
394/**\r
395 Receive data from the socket.\r
396\r
397 @param[in] Tcp4Io The Tcp4Io which wraps the socket to be destroyed.\r
398 @param[in] Packet The buffer to hold the data copy from the soket rx buffer.\r
399 @param[in] AsyncMode Is this receive asyncronous or not.\r
400 @param[in] Timeout The time to wait for receiving the amount of data the Packet\r
401 can hold.\r
402\r
403 @retval EFI_SUCCESS The required amount of data is received from the socket.\r
404 @retval EFI_OUT_OF_RESOURCES Failed to allocate momery.\r
405 @retval EFI_TIMEOUT Failed to receive the required amount of data in the\r
406 specified time period.\r
407 @retval Others Some expected error happened.\r
408**/\r
409EFI_STATUS\r
410Tcp4IoReceive (\r
411 IN TCP4_IO *Tcp4Io,\r
412 IN NET_BUF *Packet,\r
413 IN BOOLEAN AsyncMode,\r
414 IN EFI_EVENT Timeout\r
415 )\r
416{\r
417 EFI_TCP4_PROTOCOL *Tcp4;\r
418 EFI_TCP4_RECEIVE_DATA RxData;\r
419 EFI_STATUS Status;\r
420 NET_FRAGMENT *Fragment;\r
421 UINT32 FragmentCount;\r
422 UINT32 CurrentFragment;\r
423\r
424 FragmentCount = Packet->BlockOpNum;\r
425 Fragment = AllocatePool (FragmentCount * sizeof (NET_FRAGMENT));\r
426 if (Fragment == NULL) {\r
427 return EFI_OUT_OF_RESOURCES;\r
428 }\r
429 //\r
430 // Build the fragment table.\r
431 //\r
432 NetbufBuildExt (Packet, Fragment, &FragmentCount);\r
433\r
434 RxData.FragmentCount = 1;\r
435 Tcp4Io->RxToken.Packet.RxData = &RxData;\r
436 CurrentFragment = 0;\r
437 Tcp4 = Tcp4Io->Tcp4;\r
438 Status = EFI_SUCCESS;\r
439\r
440 while (CurrentFragment < FragmentCount) {\r
441 RxData.DataLength = Fragment[CurrentFragment].Len;\r
442 RxData.FragmentTable[0].FragmentLength = Fragment[CurrentFragment].Len;\r
443 RxData.FragmentTable[0].FragmentBuffer = Fragment[CurrentFragment].Bulk;\r
444\r
445 Status = Tcp4->Receive (Tcp4, &Tcp4Io->RxToken);\r
446 if (EFI_ERROR (Status)) {\r
447 goto ON_EXIT;\r
448 }\r
449\r
450 while (!Tcp4Io->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
451 //\r
452 // Poll until some data is received or something error happens.\r
453 //\r
454 Tcp4->Poll (Tcp4);\r
455 }\r
456\r
457 if (!Tcp4Io->IsRxDone) {\r
458 //\r
459 // Timeout occurs, cancel the receive request.\r
460 //\r
461 Tcp4->Cancel (Tcp4, &Tcp4Io->RxToken.CompletionToken);\r
462\r
463 Status = EFI_TIMEOUT;\r
464 goto ON_EXIT;\r
465 } else {\r
466 Tcp4Io->IsRxDone = FALSE;\r
467 }\r
468\r
469 if (EFI_ERROR (Tcp4Io->RxToken.CompletionToken.Status)) {\r
470 Status = Tcp4Io->RxToken.CompletionToken.Status;\r
471 goto ON_EXIT;\r
472 }\r
473\r
474 Fragment[CurrentFragment].Len -= RxData.FragmentTable[0].FragmentLength;\r
475 if (Fragment[CurrentFragment].Len == 0) {\r
476 CurrentFragment++;\r
477 } else {\r
478 Fragment[CurrentFragment].Bulk += RxData.FragmentTable[0].FragmentLength;\r
479 }\r
480 }\r
481\r
482ON_EXIT:\r
483\r
484 gBS->FreePool (Fragment);\r
485\r
486 return Status;\r
487}\r