2 Implementation of initializing a network adapter.
4 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 Call UNDI to initialize the interface.
14 @param Snp Pointer to snp driver structure.
15 @param CableDetectFlag Do/don't detect the cable (depending on what
18 @retval EFI_SUCCESS UNDI is initialized successfully.
19 @retval EFI_DEVICE_ERROR UNDI could not be initialized.
20 @retval Other Other errors as indicated.
26 UINT16 CableDetectFlag
29 PXE_CPB_INITIALIZE
*Cpb
;
36 if (Snp
->TxRxBufferSize
!= 0) {
37 Status
= Snp
->PciIo
->AllocateBuffer (
41 SNP_MEM_PAGES (Snp
->TxRxBufferSize
),
46 if (Status
!= EFI_SUCCESS
) {
49 "\nSnp->PxeInit() AllocateBuffer %xh (%r)\n",
59 Snp
->TxRxBuffer
= Addr
;
62 Cpb
->MemoryAddr
= (UINT64
)(UINTN
)Snp
->TxRxBuffer
;
64 Cpb
->MemoryLength
= Snp
->TxRxBufferSize
;
67 // let UNDI decide/detect these values
75 Cpb
->DuplexMode
= PXE_DUPLEX_DEFAULT
;
77 Cpb
->LoopBackMode
= LOOPBACK_NORMAL
;
79 Snp
->Cdb
.OpCode
= PXE_OPCODE_INITIALIZE
;
80 Snp
->Cdb
.OpFlags
= CableDetectFlag
;
82 Snp
->Cdb
.CPBsize
= (UINT16
)sizeof (PXE_CPB_INITIALIZE
);
83 Snp
->Cdb
.DBsize
= (UINT16
)sizeof (PXE_DB_INITIALIZE
);
85 Snp
->Cdb
.CPBaddr
= (UINT64
)(UINTN
)Snp
->Cpb
;
86 Snp
->Cdb
.DBaddr
= (UINT64
)(UINTN
)Snp
->Db
;
88 Snp
->Cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
89 Snp
->Cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
90 Snp
->Cdb
.IFnum
= Snp
->IfNum
;
91 Snp
->Cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
93 DEBUG ((DEBUG_NET
, "\nSnp->undi.initialize() "));
95 (*Snp
->IssueUndi32Command
)((UINT64
)(UINTN
)&Snp
->Cdb
);
98 // There are two fields need to be checked here:
99 // First is the upper two bits (14 & 15) in the CDB.StatFlags field. Until these bits change to report
100 // PXE_STATFLAGS_COMMAND_COMPLETE or PXE_STATFLAGS_COMMAND_FAILED, the command has not been executed by the UNDI.
101 // Second is the CDB.StatCode field. After command execution completes, either successfully or not,
102 // the CDB.StatCode field contains the result of the command execution.
104 if ((((Snp
->Cdb
.StatFlags
) & PXE_STATFLAGS_STATUS_MASK
) == PXE_STATFLAGS_COMMAND_COMPLETE
) &&
105 (Snp
->Cdb
.StatCode
== PXE_STATCODE_SUCCESS
))
108 // If cable detect feature is enabled in CDB.OpFlags, check the CDB.StatFlags to see if there is an
109 // active connection to this network device. If the no media StatFlag is set, the UNDI and network
110 // device are still initialized.
112 if (CableDetectFlag
== PXE_OPFLAGS_INITIALIZE_DETECT_CABLE
) {
113 if (((Snp
->Cdb
.StatFlags
) & PXE_STATFLAGS_INITIALIZED_NO_MEDIA
) != PXE_STATFLAGS_INITIALIZED_NO_MEDIA
) {
114 Snp
->Mode
.MediaPresent
= TRUE
;
116 Snp
->Mode
.MediaPresent
= FALSE
;
120 Snp
->Mode
.State
= EfiSimpleNetworkInitialized
;
121 Status
= EFI_SUCCESS
;
125 "\nSnp->undi.initialize() %xh:%xh\n",
130 if (Snp
->TxRxBuffer
!= NULL
) {
131 Snp
->PciIo
->FreeBuffer (
133 SNP_MEM_PAGES (Snp
->TxRxBufferSize
),
134 (VOID
*)Snp
->TxRxBuffer
138 Snp
->TxRxBuffer
= NULL
;
140 Status
= EFI_DEVICE_ERROR
;
147 Resets a network adapter and allocates the transmit and receive buffers
148 required by the network interface; optionally, also requests allocation of
149 additional transmit and receive buffers.
151 This function allocates the transmit and receive buffers required by the network
152 interface. If this allocation fails, then EFI_OUT_OF_RESOURCES is returned.
153 If the allocation succeeds and the network interface is successfully initialized,
154 then EFI_SUCCESS will be returned.
156 @param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
158 @param ExtraRxBufferSize The size, in bytes, of the extra receive buffer space
159 that the driver should allocate for the network interface.
160 Some network interfaces will not be able to use the
161 extra buffer, and the caller will not know if it is
163 @param ExtraTxBufferSize The size, in bytes, of the extra transmit buffer space
164 that the driver should allocate for the network interface.
165 Some network interfaces will not be able to use the
166 extra buffer, and the caller will not know if it is
169 @retval EFI_SUCCESS The network interface was initialized.
170 @retval EFI_NOT_STARTED The network interface has not been started.
171 @retval EFI_OUT_OF_RESOURCES There was not enough memory for the transmit and
173 @retval EFI_INVALID_PARAMETER This parameter was NULL or did not point to a valid
174 EFI_SIMPLE_NETWORK_PROTOCOL structure.
175 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
176 @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
181 SnpUndi32Initialize (
182 IN EFI_SIMPLE_NETWORK_PROTOCOL
*This
,
183 IN UINTN ExtraRxBufferSize OPTIONAL
,
184 IN UINTN ExtraTxBufferSize OPTIONAL
187 EFI_STATUS EfiStatus
;
192 return EFI_INVALID_PARAMETER
;
195 Snp
= EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This
);
197 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
200 EfiStatus
= EFI_INVALID_PARAMETER
;
204 switch (Snp
->Mode
.State
) {
205 case EfiSimpleNetworkStarted
:
208 case EfiSimpleNetworkStopped
:
209 EfiStatus
= EFI_NOT_STARTED
;
213 EfiStatus
= EFI_DEVICE_ERROR
;
217 EfiStatus
= gBS
->CreateEvent (
220 &SnpWaitForPacketNotify
,
222 &Snp
->Snp
.WaitForPacket
225 if (EFI_ERROR (EfiStatus
)) {
226 Snp
->Snp
.WaitForPacket
= NULL
;
227 EfiStatus
= EFI_DEVICE_ERROR
;
234 Snp
->Mode
.MCastFilterCount
= 0;
235 Snp
->Mode
.ReceiveFilterSetting
= 0;
236 ZeroMem (Snp
->Mode
.MCastFilter
, sizeof Snp
->Mode
.MCastFilter
);
238 &Snp
->Mode
.CurrentAddress
,
239 &Snp
->Mode
.PermanentAddress
,
240 sizeof (EFI_MAC_ADDRESS
)
244 // Compute tx/rx buffer sizes based on UNDI init info and parameters.
246 Snp
->TxRxBufferSize
= (UINT32
)(Snp
->InitInfo
.MemoryRequired
+ ExtraRxBufferSize
+ ExtraTxBufferSize
);
249 // If UNDI support cable detect for INITIALIZE command, try it first.
251 if (Snp
->CableDetectSupported
) {
252 if (PxeInit (Snp
, PXE_OPFLAGS_INITIALIZE_DETECT_CABLE
) == EFI_SUCCESS
) {
257 Snp
->Mode
.MediaPresent
= FALSE
;
259 EfiStatus
= PxeInit (Snp
, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE
);
261 if (EFI_ERROR (EfiStatus
)) {
262 gBS
->CloseEvent (Snp
->Snp
.WaitForPacket
);
267 // Try to update the MediaPresent field of EFI_SIMPLE_NETWORK_MODE if the UNDI support it.
269 if (Snp
->MediaStatusSupported
) {
270 PxeGetStatus (Snp
, NULL
, FALSE
);
274 gBS
->RestoreTPL (OldTpl
);