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