69154fc0c71e831396bd8b55b9754f90c168d52f
[mirror_edk2.git] / MdeModulePkg / Universal / Network / SnpDxe / Initialize.c
1 /** @file\r
2 Copyright (c) 2004 - 2007, Intel Corporation\r
3 All rights reserved. This program and the accompanying materials\r
4 are licensed and made available under the terms and conditions of the BSD License\r
5 which accompanies this distribution.  The full text of the license may be found at\r
6 http://opensource.org/licenses/bsd-license.php\r
7 \r
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
10 \r
11 Module name:\r
12   initialize.c\r
13 \r
14 Abstract:\r
15 \r
16 Revision history:\r
17   2000-Feb-09 M(f)J   Genesis.\r
18 \r
19 **/\r
20 \r
21 \r
22 #include "Snp.h"\r
23 \r
24 VOID\r
25 EFIAPI\r
26 SnpWaitForPacketNotify (\r
27   IN EFI_EVENT  Event,\r
28   IN VOID       *SnpPtr\r
29   );\r
30 \r
31 \r
32 /**\r
33   this routine calls undi to initialize the interface.\r
34 \r
35   @param  snp                   pointer to snp driver structure\r
36   @param  CableDetectFlag       Do/don't detect the cable (depending on what undi\r
37                                 supports)\r
38 \r
39 \r
40 **/\r
41 EFI_STATUS\r
42 pxe_init (\r
43   SNP_DRIVER *snp,\r
44   UINT16     CableDetectFlag\r
45   )\r
46 {\r
47   PXE_CPB_INITIALIZE  *cpb;\r
48   VOID                *addr;\r
49   EFI_STATUS          Status;\r
50 \r
51   cpb = snp->cpb;\r
52   if (snp->tx_rx_bufsize != 0) {\r
53     Status = snp->IoFncs->AllocateBuffer (\r
54                             snp->IoFncs,\r
55                             AllocateAnyPages,\r
56                             EfiBootServicesData,\r
57                             SNP_MEM_PAGES (snp->tx_rx_bufsize),\r
58                             &addr,\r
59                             0\r
60                             );\r
61 \r
62     if (Status != EFI_SUCCESS) {\r
63       DEBUG (\r
64         (EFI_D_ERROR,\r
65         "\nsnp->pxe_init()  AllocateBuffer  %xh (%r)\n",\r
66         Status,\r
67         Status)\r
68         );\r
69 \r
70       return Status;\r
71     }\r
72 \r
73     ASSERT (addr);\r
74 \r
75     snp->tx_rx_buffer = addr;\r
76   }\r
77 \r
78   cpb->MemoryAddr   = (UINT64)(UINTN) snp->tx_rx_buffer;\r
79 \r
80   cpb->MemoryLength = snp->tx_rx_bufsize;\r
81 \r
82   //\r
83   // let UNDI decide/detect these values\r
84   //\r
85   cpb->LinkSpeed      = 0;\r
86   cpb->TxBufCnt       = 0;\r
87   cpb->TxBufSize      = 0;\r
88   cpb->RxBufCnt       = 0;\r
89   cpb->RxBufSize      = 0;\r
90 \r
91   cpb->DuplexMode         = PXE_DUPLEX_DEFAULT;\r
92 \r
93   cpb->LoopBackMode       = LOOPBACK_NORMAL;\r
94 \r
95   snp->cdb.OpCode     = PXE_OPCODE_INITIALIZE;\r
96   snp->cdb.OpFlags    = CableDetectFlag;\r
97 \r
98   snp->cdb.CPBsize    = sizeof (PXE_CPB_INITIALIZE);\r
99   snp->cdb.DBsize     = sizeof (PXE_DB_INITIALIZE);\r
100 \r
101   snp->cdb.CPBaddr    = (UINT64)(UINTN) snp->cpb;\r
102   snp->cdb.DBaddr     = (UINT64)(UINTN) snp->db;\r
103 \r
104   snp->cdb.StatCode   = PXE_STATCODE_INITIALIZE;\r
105   snp->cdb.StatFlags  = PXE_STATFLAGS_INITIALIZE;\r
106   snp->cdb.IFnum      = snp->if_num;\r
107   snp->cdb.Control    = PXE_CONTROL_LAST_CDB_IN_LIST;\r
108 \r
109   DEBUG ((EFI_D_NET, "\nsnp->undi.initialize()  "));\r
110 \r
111   (*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);\r
112 \r
113   if (snp->cdb.StatCode == PXE_STATCODE_SUCCESS) {\r
114     snp->mode.State = EfiSimpleNetworkInitialized;\r
115 \r
116     Status          = EFI_SUCCESS;\r
117   } else {\r
118     DEBUG (\r
119       (EFI_D_WARN,\r
120       "\nsnp->undi.initialize()  %xh:%xh\n",\r
121       snp->cdb.StatFlags,\r
122       snp->cdb.StatCode)\r
123       );\r
124 \r
125     if (snp->tx_rx_buffer != NULL) {\r
126       snp->IoFncs->FreeBuffer (\r
127                     snp->IoFncs,\r
128                     SNP_MEM_PAGES (snp->tx_rx_bufsize),\r
129                     (VOID *) snp->tx_rx_buffer\r
130                     );\r
131     }\r
132 \r
133     snp->tx_rx_buffer = NULL;\r
134 \r
135     Status            = EFI_DEVICE_ERROR;\r
136   }\r
137 \r
138   return Status;\r
139 }\r
140 \r
141 \r
142 /**\r
143   This is the SNP interface routine for initializing the interface\r
144   This routine basically retrieves snp structure, checks the SNP state and\r
145   calls the pxe_initialize routine to actually do the undi initialization\r
146 \r
147   @param  this                  context pointer\r
148   @param  extra_rx_buffer_size  optional parameter, indicates extra space for\r
149                                 rx_buffers\r
150   @param  extra_tx_buffer_size  optional parameter, indicates extra space for\r
151                                 tx_buffers\r
152 \r
153 \r
154 **/\r
155 EFI_STATUS\r
156 EFIAPI\r
157 snp_undi32_initialize (\r
158   IN EFI_SIMPLE_NETWORK_PROTOCOL *this,\r
159   IN UINTN                       extra_rx_buffer_size OPTIONAL,\r
160   IN UINTN                       extra_tx_buffer_size OPTIONAL\r
161   )\r
162 {\r
163   EFI_STATUS  EfiStatus;\r
164   SNP_DRIVER  *snp;\r
165   EFI_TPL     OldTpl;\r
166 \r
167   //\r
168   //\r
169   //\r
170   if (this == NULL) {\r
171     return EFI_INVALID_PARAMETER;\r
172   }\r
173 \r
174   snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);\r
175 \r
176   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
177 \r
178   if (snp == NULL) {\r
179     EfiStatus = EFI_INVALID_PARAMETER;\r
180     goto ON_EXIT;\r
181   }\r
182 \r
183   switch (snp->mode.State) {\r
184   case EfiSimpleNetworkStarted:\r
185     break;\r
186 \r
187   case EfiSimpleNetworkStopped:\r
188     EfiStatus = EFI_NOT_STARTED;\r
189     goto ON_EXIT;\r
190 \r
191   default:\r
192     EfiStatus = EFI_DEVICE_ERROR;\r
193     goto ON_EXIT;\r
194   }\r
195 \r
196   EfiStatus = gBS->CreateEvent (\r
197                     EVT_NOTIFY_WAIT,\r
198                     TPL_NOTIFY,\r
199                     &SnpWaitForPacketNotify,\r
200                     snp,\r
201                     &snp->snp.WaitForPacket\r
202                     );\r
203 \r
204   if (EFI_ERROR (EfiStatus)) {\r
205     snp->snp.WaitForPacket = NULL;\r
206     EfiStatus = EFI_DEVICE_ERROR;\r
207     goto ON_EXIT;\r
208   }\r
209   //\r
210   //\r
211   //\r
212   snp->mode.MCastFilterCount      = 0;\r
213   snp->mode.ReceiveFilterSetting  = 0;\r
214   ZeroMem (snp->mode.MCastFilter, sizeof snp->mode.MCastFilter);\r
215   CopyMem (\r
216     &snp->mode.CurrentAddress,\r
217     &snp->mode.PermanentAddress,\r
218     sizeof (EFI_MAC_ADDRESS)\r
219     );\r
220 \r
221   //\r
222   // Compute tx/rx buffer sizes based on UNDI init info and parameters.\r
223   //\r
224   snp->tx_rx_bufsize = (UINT32) (snp->init_info.MemoryRequired + extra_rx_buffer_size + extra_tx_buffer_size);\r
225 \r
226   if (snp->mode.MediaPresentSupported) {\r
227     if (pxe_init (snp, PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) == EFI_SUCCESS) {\r
228       snp->mode.MediaPresent = TRUE;\r
229       goto ON_EXIT;\r
230     }\r
231   }\r
232 \r
233   snp->mode.MediaPresent  = FALSE;\r
234 \r
235   EfiStatus               = pxe_init (snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE);\r
236 \r
237   if (EFI_ERROR (EfiStatus)) {\r
238     gBS->CloseEvent (snp->snp.WaitForPacket);\r
239   }\r
240 \r
241 ON_EXIT:\r
242   gBS->RestoreTPL (OldTpl);\r
243 \r
244   return EfiStatus;\r
245 }\r