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