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
PxeInit(SNP_DRIVER * Snp,UINT16 CableDetectFlag)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
SnpUndi32Initialize(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN UINTN ExtraRxBufferSize OPTIONAL,IN UINTN ExtraTxBufferSize OPTIONAL)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