1 /** @file 2 Implementation of initializing a network adapter. 3 4 Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials are licensed 6 and made available under the terms and conditions of the BSD License which 7 accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 16 #include "Snp.h" 17 18 /** 19 Call UNDI to initialize the interface. 20 21 @param Snp Pointer to snp driver structure. 22 @param CableDetectFlag Do/don't detect the cable (depending on what 23 undi supports). 24 25 @retval EFI_SUCCESS UNDI is initialized successfully. 26 @retval EFI_DEVICE_ERROR UNDI could not be initialized. 27 @retval Other Other errors as indicated. 28 29 **/ 30 EFI_STATUS 31 PxeInit ( 32 SNP_DRIVER *Snp, 33 UINT16 CableDetectFlag 34 ) 35 { 36 PXE_CPB_INITIALIZE *Cpb; 37 VOID *Addr; 38 EFI_STATUS Status; 39 40 Cpb = Snp->Cpb; 41 if (Snp->TxRxBufferSize != 0) { 42 Status = Snp->PciIo->AllocateBuffer ( 43 Snp->PciIo, 44 AllocateAnyPages, 45 EfiBootServicesData, 46 SNP_MEM_PAGES (Snp->TxRxBufferSize), 47 &Addr, 48 0 49 ); 50 51 if (Status != EFI_SUCCESS) { 52 DEBUG ( 53 (EFI_D_ERROR, 54 "\nSnp->PxeInit() AllocateBuffer %xh (%r)\n", 55 Status, 56 Status) 57 ); 58 59 return Status; 60 } 61 62 ASSERT (Addr); 63 64 Snp->TxRxBuffer = Addr; 65 } 66 67 Cpb->MemoryAddr = (UINT64)(UINTN) Snp->TxRxBuffer; 68 69 Cpb->MemoryLength = Snp->TxRxBufferSize; 70 71 // 72 // let UNDI decide/detect these values 73 // 74 Cpb->LinkSpeed = 0; 75 Cpb->TxBufCnt = 0; 76 Cpb->TxBufSize = 0; 77 Cpb->RxBufCnt = 0; 78 Cpb->RxBufSize = 0; 79 80 Cpb->DuplexMode = PXE_DUPLEX_DEFAULT; 81 82 Cpb->LoopBackMode = LOOPBACK_NORMAL; 83 84 Snp->Cdb.OpCode = PXE_OPCODE_INITIALIZE; 85 Snp->Cdb.OpFlags = CableDetectFlag; 86 87 Snp->Cdb.CPBsize = (UINT16) sizeof (PXE_CPB_INITIALIZE); 88 Snp->Cdb.DBsize = (UINT16) sizeof (PXE_DB_INITIALIZE); 89 90 Snp->Cdb.CPBaddr = (UINT64)(UINTN) Snp->Cpb; 91 Snp->Cdb.DBaddr = (UINT64)(UINTN) Snp->Db; 92 93 Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE; 94 Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; 95 Snp->Cdb.IFnum = Snp->IfNum; 96 Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; 97 98 DEBUG ((EFI_D_NET, "\nSnp->undi.initialize() ")); 99 100 (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb); 101 102 if (Snp->Cdb.StatCode == PXE_STATCODE_SUCCESS) { 103 Snp->Mode.State = EfiSimpleNetworkInitialized; 104 105 Status = EFI_SUCCESS; 106 } else { 107 DEBUG ( 108 (EFI_D_WARN, 109 "\nSnp->undi.initialize() %xh:%xh\n", 110 Snp->Cdb.StatFlags, 111 Snp->Cdb.StatCode) 112 ); 113 114 if (Snp->TxRxBuffer != NULL) { 115 Snp->PciIo->FreeBuffer ( 116 Snp->PciIo, 117 SNP_MEM_PAGES (Snp->TxRxBufferSize), 118 (VOID *) Snp->TxRxBuffer 119 ); 120 } 121 122 Snp->TxRxBuffer = NULL; 123 124 Status = EFI_DEVICE_ERROR; 125 } 126 127 return Status; 128 } 129 130 131 /** 132 Resets a network adapter and allocates the transmit and receive buffers 133 required by the network interface; optionally, also requests allocation of 134 additional transmit and receive buffers. 135 136 This function allocates the transmit and receive buffers required by the network 137 interface. If this allocation fails, then EFI_OUT_OF_RESOURCES is returned. 138 If the allocation succeeds and the network interface is successfully initialized, 139 then EFI_SUCCESS will be returned. 140 141 @param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance. 142 143 @param ExtraRxBufferSize The size, in bytes, of the extra receive buffer space 144 that the driver should allocate for the network interface. 145 Some network interfaces will not be able to use the 146 extra buffer, and the caller will not know if it is 147 actually being used. 148 @param ExtraTxBufferSize The size, in bytes, of the extra transmit buffer space 149 that the driver should allocate for the network interface. 150 Some network interfaces will not be able to use the 151 extra buffer, and the caller will not know if it is 152 actually being used. 153 154 @retval EFI_SUCCESS The network interface was initialized. 155 @retval EFI_NOT_STARTED The network interface has not been started. 156 @retval EFI_OUT_OF_RESOURCES There was not enough memory for the transmit and 157 receive buffers. 158 @retval EFI_INVALID_PARAMETER This parameter was NULL or did not point to a valid 159 EFI_SIMPLE_NETWORK_PROTOCOL structure. 160 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. 161 @retval EFI_UNSUPPORTED The increased buffer size feature is not supported. 162 163 **/ 164 EFI_STATUS 165 EFIAPI 166 SnpUndi32Initialize ( 167 IN EFI_SIMPLE_NETWORK_PROTOCOL *This, 168 IN UINTN ExtraRxBufferSize OPTIONAL, 169 IN UINTN ExtraTxBufferSize OPTIONAL 170 ) 171 { 172 EFI_STATUS EfiStatus; 173 SNP_DRIVER *Snp; 174 EFI_TPL OldTpl; 175 176 if (This == NULL) { 177 return EFI_INVALID_PARAMETER; 178 } 179 180 Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); 181 182 OldTpl = gBS->RaiseTPL (TPL_CALLBACK); 183 184 if (Snp == NULL) { 185 EfiStatus = EFI_INVALID_PARAMETER; 186 goto ON_EXIT; 187 } 188 189 switch (Snp->Mode.State) { 190 case EfiSimpleNetworkStarted: 191 break; 192 193 case EfiSimpleNetworkStopped: 194 EfiStatus = EFI_NOT_STARTED; 195 goto ON_EXIT; 196 197 default: 198 EfiStatus = EFI_DEVICE_ERROR; 199 goto ON_EXIT; 200 } 201 202 EfiStatus = gBS->CreateEvent ( 203 EVT_NOTIFY_WAIT, 204 TPL_NOTIFY, 205 &SnpWaitForPacketNotify, 206 Snp, 207 &Snp->Snp.WaitForPacket 208 ); 209 210 if (EFI_ERROR (EfiStatus)) { 211 Snp->Snp.WaitForPacket = NULL; 212 EfiStatus = EFI_DEVICE_ERROR; 213 goto ON_EXIT; 214 } 215 // 216 // 217 // 218 Snp->Mode.MCastFilterCount = 0; 219 Snp->Mode.ReceiveFilterSetting = 0; 220 ZeroMem (Snp->Mode.MCastFilter, sizeof Snp->Mode.MCastFilter); 221 CopyMem ( 222 &Snp->Mode.CurrentAddress, 223 &Snp->Mode.PermanentAddress, 224 sizeof (EFI_MAC_ADDRESS) 225 ); 226 227 // 228 // Compute tx/rx buffer sizes based on UNDI init info and parameters. 229 // 230 Snp->TxRxBufferSize = (UINT32) (Snp->InitInfo.MemoryRequired + ExtraRxBufferSize + ExtraTxBufferSize); 231 232 if (Snp->Mode.MediaPresentSupported) { 233 if (PxeInit (Snp, PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) == EFI_SUCCESS) { 234 Snp->Mode.MediaPresent = TRUE; 235 goto ON_EXIT; 236 } 237 } 238 239 Snp->Mode.MediaPresent = FALSE; 240 241 EfiStatus = PxeInit (Snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE); 242 243 if (EFI_ERROR (EfiStatus)) { 244 gBS->CloseEvent (Snp->Snp.WaitForPacket); 245 } 246 247 ON_EXIT: 248 gBS->RestoreTPL (OldTpl); 249 250 return EfiStatus; 251 } 252