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