3 Copyright (c) 2004 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 #include "IScsiImpl.h"
32 The common notify function associated with various Tcp4Io events.
36 Event - The event signaled.
37 Contect - The context.
45 *((BOOLEAN
*) Context
) = TRUE
;
51 IN EFI_HANDLE Controller
,
52 IN TCP4_IO_CONFIG_DATA
*ConfigData
,
59 Create a TCP socket with the specified configuration data.
63 Image - The handle of the driver image.
64 Controller - The handle of the controller.
65 ConfigData - The Tcp4 configuration data.
70 EFI_SUCCESS - The TCP socket is created and configured.
71 other - Failed to create the TCP socket or configure it.
76 EFI_TCP4_PROTOCOL
*Tcp4
;
77 EFI_TCP4_CONFIG_DATA Tcp4ConfigData
;
78 EFI_TCP4_OPTION ControlOption
;
79 EFI_TCP4_ACCESS_POINT
*AccessPoint
;
81 Tcp4Io
->Handle
= NULL
;
82 Tcp4Io
->ConnToken
.CompletionToken
.Event
= NULL
;
83 Tcp4Io
->TxToken
.CompletionToken
.Event
= NULL
;
84 Tcp4Io
->RxToken
.CompletionToken
.Event
= NULL
;
85 Tcp4Io
->CloseToken
.CompletionToken
.Event
= NULL
;
89 // Create the TCP4 child instance and get the TCP4 protocol.
91 Status
= NetLibCreateServiceChild (
94 &gEfiTcp4ServiceBindingProtocolGuid
,
97 if (EFI_ERROR (Status
)) {
101 Status
= gBS
->OpenProtocol (
103 &gEfiTcp4ProtocolGuid
,
104 (VOID
**)&Tcp4Io
->Tcp4
,
107 EFI_OPEN_PROTOCOL_BY_DRIVER
109 if (EFI_ERROR (Status
)) {
113 Tcp4Io
->Image
= Image
;
114 Tcp4Io
->Controller
= Controller
;
118 // Set the configuration parameters.
120 ControlOption
.ReceiveBufferSize
= 0x200000;
121 ControlOption
.SendBufferSize
= 0x200000;
122 ControlOption
.MaxSynBackLog
= 0;
123 ControlOption
.ConnectionTimeout
= 0;
124 ControlOption
.DataRetries
= 6;
125 ControlOption
.FinTimeout
= 0;
126 ControlOption
.TimeWaitTimeout
= 0;
127 ControlOption
.KeepAliveProbes
= 4;
128 ControlOption
.KeepAliveTime
= 0;
129 ControlOption
.KeepAliveInterval
= 0;
130 ControlOption
.EnableNagle
= FALSE
;
131 ControlOption
.EnableTimeStamp
= FALSE
;
132 ControlOption
.EnableWindowScaling
= TRUE
;
133 ControlOption
.EnableSelectiveAck
= FALSE
;
134 ControlOption
.EnablePathMtuDiscovery
= FALSE
;
136 Tcp4ConfigData
.TypeOfService
= 8;
137 Tcp4ConfigData
.TimeToLive
= 255;
138 Tcp4ConfigData
.ControlOption
= &ControlOption
;
140 AccessPoint
= &Tcp4ConfigData
.AccessPoint
;
142 AccessPoint
->UseDefaultAddress
= FALSE
;
143 AccessPoint
->StationPort
= 0;
144 AccessPoint
->RemotePort
= ConfigData
->RemotePort
;
145 AccessPoint
->ActiveFlag
= TRUE
;
147 CopyMem (&AccessPoint
->StationAddress
, &ConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
148 CopyMem (&AccessPoint
->SubnetMask
, &ConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
149 CopyMem (&AccessPoint
->RemoteAddress
, &ConfigData
->RemoteIp
, sizeof (EFI_IPv4_ADDRESS
));
152 // Configure the TCP4 protocol.
154 Status
= Tcp4
->Configure (Tcp4
, &Tcp4ConfigData
);
155 if (EFI_ERROR (Status
)) {
159 if (!EFI_IP4_EQUAL (&ConfigData
->Gateway
, &mZeroIp4Addr
)) {
161 // the gateway is not zero, add the default route by hand
163 Status
= Tcp4
->Routes (Tcp4
, FALSE
, &mZeroIp4Addr
, &mZeroIp4Addr
, &ConfigData
->Gateway
);
164 if (EFI_ERROR (Status
)) {
169 // Create events for variuos asynchronous operations.
171 Status
= gBS
->CreateEvent (
172 EFI_EVENT_NOTIFY_SIGNAL
,
176 &Tcp4Io
->ConnToken
.CompletionToken
.Event
178 if (EFI_ERROR (Status
)) {
182 Status
= gBS
->CreateEvent (
183 EFI_EVENT_NOTIFY_SIGNAL
,
187 &Tcp4Io
->TxToken
.CompletionToken
.Event
189 if (EFI_ERROR (Status
)) {
193 Status
= gBS
->CreateEvent (
194 EFI_EVENT_NOTIFY_SIGNAL
,
198 &Tcp4Io
->RxToken
.CompletionToken
.Event
200 if (EFI_ERROR (Status
)) {
204 Status
= gBS
->CreateEvent (
205 EFI_EVENT_NOTIFY_SIGNAL
,
208 &Tcp4Io
->IsCloseDone
,
209 &Tcp4Io
->CloseToken
.CompletionToken
.Event
211 if (EFI_ERROR (Status
)) {
215 Tcp4Io
->IsTxDone
= FALSE
;
216 Tcp4Io
->IsRxDone
= FALSE
;
222 if (Tcp4Io
->RxToken
.CompletionToken
.Event
!= NULL
) {
223 gBS
->CloseEvent (Tcp4Io
->RxToken
.CompletionToken
.Event
);
226 if (Tcp4Io
->TxToken
.CompletionToken
.Event
!= NULL
) {
227 gBS
->CloseEvent (Tcp4Io
->TxToken
.CompletionToken
.Event
);
230 if (Tcp4Io
->ConnToken
.CompletionToken
.Event
!= NULL
) {
231 gBS
->CloseEvent (Tcp4Io
->ConnToken
.CompletionToken
.Event
);
235 Tcp4
->Configure (Tcp4
, NULL
);
239 &gEfiTcp4ProtocolGuid
,
245 NetLibDestroyServiceChild (
248 &gEfiTcp4ServiceBindingProtocolGuid
,
256 Tcp4IoDestroySocket (
267 Tcp4Io - The Tcp4Io which wraps the socket to be destroyeds.
275 EFI_TCP4_PROTOCOL
*Tcp4
;
279 Tcp4
->Configure (Tcp4
, NULL
);
281 gBS
->CloseEvent (Tcp4Io
->TxToken
.CompletionToken
.Event
);
282 gBS
->CloseEvent (Tcp4Io
->RxToken
.CompletionToken
.Event
);
283 gBS
->CloseEvent (Tcp4Io
->ConnToken
.CompletionToken
.Event
);
287 &gEfiTcp4ProtocolGuid
,
292 NetLibDestroyServiceChild (
295 &gEfiTcp4ServiceBindingProtocolGuid
,
309 Connect to the other endpoint of the TCP socket.
313 Tcp4Io - The Tcp4Io wrapping the TCP socket.
314 Timeout - The time to wait for connection done.
322 EFI_TCP4_PROTOCOL
*Tcp4
;
325 Tcp4Io
->IsConnDone
= FALSE
;
327 Status
= Tcp4
->Connect (Tcp4
, &Tcp4Io
->ConnToken
);
328 if (EFI_ERROR (Status
)) {
332 while (!Tcp4Io
->IsConnDone
&& EFI_ERROR (gBS
->CheckEvent (Timeout
))) {
336 if (!Tcp4Io
->IsConnDone
) {
337 Status
= EFI_TIMEOUT
;
339 Status
= Tcp4Io
->ConnToken
.CompletionToken
.Status
;
357 Tcp4Io - The Tcp4Io wrapping the TCP socket.
366 EFI_TCP4_PROTOCOL
*Tcp4
;
368 Tcp4Io
->CloseToken
.AbortOnClose
= TRUE
;
369 Tcp4Io
->IsCloseDone
= FALSE
;
372 Status
= Tcp4
->Close (Tcp4
, &Tcp4Io
->CloseToken
);
373 if (EFI_ERROR (Status
)) {
377 while (!Tcp4Io
->IsCloseDone
) {
391 Transmit the Packet to the other endpoint of the socket.
395 Tcp4Io - The Tcp4Io wrapping the TCP socket.
396 Packet - The packet to transmit
400 EFI_SUCCESS - The packet is trasmitted.
401 EFI_OUT_OF_RESOURCES - Failed to allocate memory.
405 EFI_TCP4_TRANSMIT_DATA
*TxData
;
406 EFI_TCP4_PROTOCOL
*Tcp4
;
409 TxData
= AllocatePool (sizeof (EFI_TCP4_TRANSMIT_DATA
) + (Packet
->BlockOpNum
- 1) * sizeof (EFI_TCP4_FRAGMENT_DATA
));
410 if (TxData
== NULL
) {
411 return EFI_OUT_OF_RESOURCES
;
415 TxData
->Urgent
= FALSE
;
416 TxData
->DataLength
= Packet
->TotalSize
;
419 // Build the fragment table.
421 TxData
->FragmentCount
= Packet
->BlockOpNum
;
422 NetbufBuildExt (Packet
, (NET_FRAGMENT
*) &TxData
->FragmentTable
[0], &TxData
->FragmentCount
);
424 Tcp4Io
->TxToken
.Packet
.TxData
= TxData
;
427 // Trasnmit the packet.
430 Status
= Tcp4
->Transmit (Tcp4
, &Tcp4Io
->TxToken
);
431 if (EFI_ERROR (Status
)) {
435 while (!Tcp4Io
->IsTxDone
) {
439 Tcp4Io
->IsTxDone
= FALSE
;
441 Status
= Tcp4Io
->TxToken
.CompletionToken
.Status
;
445 gBS
->FreePool (TxData
);
454 IN BOOLEAN AsyncMode
,
461 Receive data from the socket.
465 Tcp4Io - The Tcp4Io which wraps the socket to be destroyeds.
466 Packet - The buffer to hold the data copy from the soket rx buffer.
467 AsyncMode - Is this receive asyncronous or not.
468 Timeout - The time to wait for receiving the amount of data the Packet
473 EFI_SUCCESS - The required amount of data is received from the socket.
474 EFI_OUT_OF_RESOURCES - Failed to allocate momery.
475 EFI_TIMEOUT - Failed to receive the required amount of data in the
476 specified time period.
480 EFI_TCP4_PROTOCOL
*Tcp4
;
481 EFI_TCP4_RECEIVE_DATA RxData
;
483 NET_FRAGMENT
*Fragment
;
484 UINT32 FragmentCount
;
485 UINT32 CurrentFragment
;
487 FragmentCount
= Packet
->BlockOpNum
;
488 Fragment
= AllocatePool (FragmentCount
* sizeof (NET_FRAGMENT
));
489 if (Fragment
== NULL
) {
490 return EFI_OUT_OF_RESOURCES
;
493 // Build the fragment table.
495 NetbufBuildExt (Packet
, Fragment
, &FragmentCount
);
497 RxData
.FragmentCount
= 1;
498 Tcp4Io
->RxToken
.Packet
.RxData
= &RxData
;
501 Status
= EFI_SUCCESS
;
503 while (CurrentFragment
< FragmentCount
) {
504 RxData
.DataLength
= Fragment
[CurrentFragment
].Len
;
505 RxData
.FragmentTable
[0].FragmentLength
= Fragment
[CurrentFragment
].Len
;
506 RxData
.FragmentTable
[0].FragmentBuffer
= Fragment
[CurrentFragment
].Bulk
;
508 Status
= Tcp4
->Receive (Tcp4
, &Tcp4Io
->RxToken
);
509 if (EFI_ERROR (Status
)) {
513 while (!Tcp4Io
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
515 // Poll until some data is received or something error happens.
520 if (!Tcp4Io
->IsRxDone
) {
522 // Timeout occurs, cancel the receive request.
524 Tcp4
->Cancel (Tcp4
, &Tcp4Io
->RxToken
.CompletionToken
);
526 Status
= EFI_TIMEOUT
;
529 Tcp4Io
->IsRxDone
= FALSE
;
532 if (EFI_ERROR (Tcp4Io
->RxToken
.CompletionToken
.Status
)) {
533 Status
= Tcp4Io
->RxToken
.CompletionToken
.Status
;
537 Fragment
[CurrentFragment
].Len
-= RxData
.FragmentTable
[0].FragmentLength
;
538 if (Fragment
[CurrentFragment
].Len
== 0) {
541 Fragment
[CurrentFragment
].Bulk
+= RxData
.FragmentTable
[0].FragmentLength
;
547 gBS
->FreePool (Fragment
);