1/** @file
2
3Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved.<BR>
4
5This program and the accompanying materials
6are licensed and made available under the terms and conditions
7of the BSD License which accompanies this distribution.  The
8full text of the license may be found at
9http://opensource.org/licenses/bsd-license.php
10
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14**/
15
16#include "BiosSnp16.h"
17
18
19///
20/// EFI Driver Binding Protocol Instance
21///
22EFI_DRIVER_BINDING_PROTOCOL gBiosSnp16DriverBinding = {
23  BiosSnp16DriverBindingSupported,
24  BiosSnp16DriverBindingStart,
25  BiosSnp16DriverBindingStop,
26  0x3,
27  NULL,
28  NULL
29};
30
31///
32///  This boolean is used to determine if we should release the cached vector during an error condition.
33///
34BOOLEAN     mCachedInt1A = FALSE;
35
36//
37// Private worker functions;
38//
39
40/**
41  Start the UNDI interface.
42
43  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
44  @param Ax                  PCI address of Undi device.
45
46  @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM.
47  @retval Others           Status of start 16 bit UNDI ROM.
48**/
49EFI_STATUS
50Undi16SimpleNetworkStartUndi (
51  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice,
52  UINT16                  Ax
53  );
54
55/**
56  Start the UNDI interface
57
58  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
59
60  @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM.
61  @retval Others           Status of start 16 bit UNDI ROM.
62**/
63EFI_STATUS
64Undi16SimpleNetworkStopUndi (
65  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
66  );
67
68/**
69  Stop the UNDI interface
70
71  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
72
73  @retval EFI_DEVICE_ERROR Fail to stop 16 bit UNDI ROM.
74  @retval Others           Status of stop 16 bit UNDI ROM.
75**/
76EFI_STATUS
77Undi16SimpleNetworkCleanupUndi (
78  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
79  );
80
81/**
82  Get runtime information for Undi network interface
83
84  @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
85
86  @retval EFI_SUCCESS Sucess operation.
87  @retval Others      Fail to get runtime information for Undi network interface.
88**/
89EFI_STATUS
90Undi16SimpleNetworkGetInformation (
91  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
92  );
93
94/**
95  Get NIC type
96
97  @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
98
99  @retval EFI_SUCCESS Sucess operation.
100  @retval Others      Fail to get NIC type.
101**/
102EFI_STATUS
103Undi16SimpleNetworkGetNicType (
104  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
105  );
106
107/**
108  Get NDIS information
109
110  @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
111
112  @retval EFI_SUCCESS Sucess operation.
113  @retval Others      Fail to get NDIS information.
114**/
115EFI_STATUS
116Undi16SimpleNetworkGetNdisInfo (
117  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
118  );
119
120/**
121  Signal handlers for ExitBootServices event.
122
123  Clean up any Real-mode UNDI residue from the system
124
125  @param Event      ExitBootServices event
126  @param Context
127**/
128VOID
129EFIAPI
130Undi16SimpleNetworkEvent (
131  IN EFI_EVENT  Event,
132  IN VOID       *Context
133  );
134
135/**
136  Loads the undi driver.
137
138  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
139
140  @retval   EFI_SUCCESS   - Successfully loads undi driver.
141  @retval   EFI_NOT_FOUND - Doesn't find undi driver or undi driver load failure.
142**/
143EFI_STATUS
144Undi16SimpleNetworkLoadUndi (
145  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
146  );
147
148/**
149  Unload 16 bit UNDI Option ROM from memory
150
151  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
152
153  @return EFI_STATUS
154**/
155EFI_STATUS
156Undi16SimpleNetworkUnloadUndi (
157  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
158  );
159
160/**
161  Entry point for EFI drivers.
162
163  @param ImageHandle Handle that identifies the loaded image.
164  @param SystemTable System Table for this image.
165
166  @return EFI_STATUS Return status from EfiLibInstallAllDriverProtocols.
167**/
168EFI_STATUS
169EFIAPI
170BiosSnp16DriverEntryPoint (
171  IN EFI_HANDLE         ImageHandle,
172  IN EFI_SYSTEM_TABLE   *SystemTable
173  )
174{
175  return EfiLibInstallDriverBindingComponentName2 (
176           ImageHandle,
177           SystemTable,
178           &gBiosSnp16DriverBinding,
179           ImageHandle,
180           &gBiosSnp16ComponentName,
181           &gBiosSnp16ComponentName2
182           );
183}
184
185//
186// EFI Driver Binding Protocol Functions
187//
188/**
189  Tests to see if this driver supports a given controller.
190
191  @param This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
192  @param Controller           The handle of the controller to test.
193  @param RemainingDevicePath  A pointer to the remaining portion of a device path.
194
195  @retval EFI_SUCCESS    The driver supports given controller.
196  @retval EFI_UNSUPPORT  The driver doesn't support given controller.
197  @retval Other          Other errors prevent driver finishing to test
198                         if the driver supports given controller.
199**/
200EFI_STATUS
201EFIAPI
202BiosSnp16DriverBindingSupported (
203  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
204  IN EFI_HANDLE                   Controller,
205  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
206  )
207{
208  EFI_STATUS                Status;
209  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
210  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
211  EFI_PCI_IO_PROTOCOL       *PciIo;
212  PCI_TYPE00                Pci;
213
214  //
215  // See if the Legacy BIOS Protocol is available
216  //
217  Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
218  if (EFI_ERROR (Status)) {
219    return Status;
220  }
221  //
222  // Open the IO Abstraction(s) needed to perform the supported test
223  //
224  Status = gBS->OpenProtocol (
225                  Controller,
226                  &gEfiDevicePathProtocolGuid,
227                  (VOID **) &DevicePath,
228                  This->DriverBindingHandle,
229                  Controller,
230                  EFI_OPEN_PROTOCOL_BY_DRIVER
231                  );
232  if (EFI_ERROR (Status)) {
233    return Status;
234  }
235
236  gBS->CloseProtocol (
237        Controller,
238        &gEfiDevicePathProtocolGuid,
239        This->DriverBindingHandle,
240        Controller
241        );
242
243  //
244  // Open the IO Abstraction(s) needed to perform the supported test
245  //
246  Status = gBS->OpenProtocol (
247                  Controller,
248                  &gEfiPciIoProtocolGuid,
249                  (VOID **) &PciIo,
250                  This->DriverBindingHandle,
251                  Controller,
252                  EFI_OPEN_PROTOCOL_BY_DRIVER
253                  );
254  if (EFI_ERROR (Status)) {
255    return Status;
256  }
257  //
258  // See if this is a PCI Network Controller by looking at the Command register and
259  // Class Code Register
260  //
261  Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof (Pci) / sizeof (UINT32), &Pci);
262  if (EFI_ERROR (Status)) {
263    Status = EFI_UNSUPPORTED;
264    goto Done;
265  }
266
267  Status = EFI_UNSUPPORTED;
268  if (Pci.Hdr.ClassCode[2] == PCI_CLASS_NETWORK) {
269    Status = EFI_SUCCESS;
270  }
271
272Done:
273  gBS->CloseProtocol (
274        Controller,
275        &gEfiPciIoProtocolGuid,
276        This->DriverBindingHandle,
277        Controller
278        );
279
280  return Status;
281}
282
283/**
284  Starts the Snp device controller
285
286  @param This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
287  @param Controller           The handle of the controller to test.
288  @param RemainingDevicePath  A pointer to the remaining portion of a device path.
289
290  @retval  EFI_SUCCESS          - The device was started.
291  @retval  EFI_DEVICE_ERROR     - The device could not be started due to a device error.
292  @retval  EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
293**/
294EFI_STATUS
295EFIAPI
296BiosSnp16DriverBindingStart (
297  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
298  IN EFI_HANDLE                   Controller,
299  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
300  )
301{
302  EFI_STATUS                Status;
303  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
304  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
305  EFI_PCI_IO_PROTOCOL       *PciIo;
306  EFI_SIMPLE_NETWORK_DEV    *SimpleNetworkDevice;
307  EFI_DEV_PATH              Node;
308  UINTN                     Index;
309  UINTN                     Index2;
310  UINTN                     Segment;
311  UINTN                     Bus;
312  UINTN                     Device;
313  UINTN                     Function;
314  UINTN                     Flags;
315  UINT64                    Supports;
316
317  SimpleNetworkDevice = NULL;
318  PciIo               = NULL;
319
320  //
321  // See if the Legacy BIOS Protocol is available
322  //
323  Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
324  if (EFI_ERROR (Status)) {
325    return Status;
326  }
327  //
328  // Open the IO Abstraction(s) needed
329  //
330  Status = gBS->OpenProtocol (
331                  Controller,
332                  &gEfiDevicePathProtocolGuid,
333                  (VOID **) &DevicePath,
334                  This->DriverBindingHandle,
335                  Controller,
336                  EFI_OPEN_PROTOCOL_BY_DRIVER
337                  );
338  if (EFI_ERROR (Status)) {
339    goto Done;
340  }
341
342  Status = gBS->OpenProtocol (
343                  Controller,
344                  &gEfiPciIoProtocolGuid,
345                  (VOID **) &PciIo,
346                  This->DriverBindingHandle,
347                  Controller,
348                  EFI_OPEN_PROTOCOL_BY_DRIVER
349                  );
350  if (EFI_ERROR (Status)) {
351    goto Done;
352  }
353
354  Status = PciIo->Attributes (
355                    PciIo,
356                    EfiPciIoAttributeOperationSupported,
357                    0,
358                    &Supports
359                    );
360  if (!EFI_ERROR (Status)) {
361    Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
362    Status = PciIo->Attributes (
363                      PciIo,
364                      EfiPciIoAttributeOperationEnable,
365                      Supports,
366                      NULL
367                      );
368  }
369
370  if (EFI_ERROR (Status)) {
371    goto Done;
372  }
373  //
374  // Check to see if there is a legacy option ROM image associated with this PCI device
375  //
376  Status = LegacyBios->CheckPciRom (
377                         LegacyBios,
378                         Controller,
379                         NULL,
380                         NULL,
381                         &Flags
382                         );
383  if (EFI_ERROR (Status)) {
384    goto Done;
385  }
386  //
387  // Post the legacy option ROM if it is available.
388  //
389  Status = LegacyBios->InstallPciRom (
390                         LegacyBios,
391                         Controller,
392                         NULL,
393                         &Flags,
394                         NULL,
395                         NULL,
396                         NULL,
397                         NULL
398                         );
399  if (EFI_ERROR (Status)) {
400    goto Done;
401  }
402  //
403  // Allocate memory for this SimpleNetwork device instance
404  //
405  Status = gBS->AllocatePool (
406                  EfiBootServicesData,
407                  sizeof (EFI_SIMPLE_NETWORK_DEV),
408                  (VOID **) &SimpleNetworkDevice
409                  );
410  if (EFI_ERROR (Status)) {
411    Status = EFI_OUT_OF_RESOURCES;
412    goto Done;
413  }
414
415  ZeroMem (SimpleNetworkDevice, sizeof (EFI_SIMPLE_NETWORK_DEV));
416
417  //
418  // Initialize the SimpleNetwork device instance
419  //
420  SimpleNetworkDevice->Signature      = EFI_SIMPLE_NETWORK_DEV_SIGNATURE;
421  SimpleNetworkDevice->LegacyBios     = LegacyBios;
422  SimpleNetworkDevice->BaseDevicePath = DevicePath;
423  SimpleNetworkDevice->PciIo          = PciIo;
424
425  //
426  // Initialize the Nii Protocol
427  //
428  SimpleNetworkDevice->Nii.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;
429  SimpleNetworkDevice->Nii.Type     = EfiNetworkInterfaceUndi;
430
431  CopyMem (&SimpleNetworkDevice->Nii.StringId, "UNDI", 4);
432
433  //
434  // Load 16 bit UNDI Option ROM into Memory
435  //
436  Status = Undi16SimpleNetworkLoadUndi (SimpleNetworkDevice);
437  if (EFI_ERROR (Status)) {
438    DEBUG ((DEBUG_NET, "ERROR : Could not load UNDI.  Status = %r\n", Status));
439    goto Done;
440  }
441
442  SimpleNetworkDevice->UndiLoaded = TRUE;
443
444  //
445  // Call PXENV_START_UNDI - Initilizes the UNID interface for use.
446  //
447  PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
448  Status = Undi16SimpleNetworkStartUndi (
449             SimpleNetworkDevice,
450             (UINT16) ((Bus << 0x8) | (Device << 0x3) | (Function))
451             );
452  if (EFI_ERROR (Status)) {
453    DEBUG ((DEBUG_NET, "ERROR : Could not StartUndi.  Status = %r\n", Status));
454    goto Done;
455  }
456  //
457  // Initialize the Simple Network Protocol
458  //
459  DEBUG ((DEBUG_NET, "Initialize SimpleNetworkDevice instance\n"));
460
461  SimpleNetworkDevice->SimpleNetwork.Revision       = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
462  SimpleNetworkDevice->SimpleNetwork.Start          = Undi16SimpleNetworkStart;
463  SimpleNetworkDevice->SimpleNetwork.Stop           = Undi16SimpleNetworkStop;
464  SimpleNetworkDevice->SimpleNetwork.Initialize     = Undi16SimpleNetworkInitialize;
465  SimpleNetworkDevice->SimpleNetwork.Reset          = Undi16SimpleNetworkReset;
466  SimpleNetworkDevice->SimpleNetwork.Shutdown       = Undi16SimpleNetworkShutdown;
467  SimpleNetworkDevice->SimpleNetwork.ReceiveFilters = Undi16SimpleNetworkReceiveFilters;
468  SimpleNetworkDevice->SimpleNetwork.StationAddress = Undi16SimpleNetworkStationAddress;
469  SimpleNetworkDevice->SimpleNetwork.Statistics     = Undi16SimpleNetworkStatistics;
470  SimpleNetworkDevice->SimpleNetwork.MCastIpToMac   = Undi16SimpleNetworkMCastIpToMac;
471  SimpleNetworkDevice->SimpleNetwork.NvData         = Undi16SimpleNetworkNvData;
472  SimpleNetworkDevice->SimpleNetwork.GetStatus      = Undi16SimpleNetworkGetStatus;
473  SimpleNetworkDevice->SimpleNetwork.Transmit       = Undi16SimpleNetworkTransmit;
474  SimpleNetworkDevice->SimpleNetwork.Receive        = Undi16SimpleNetworkReceive;
475  SimpleNetworkDevice->SimpleNetwork.Mode           = &(SimpleNetworkDevice->SimpleNetworkMode);
476
477  Status = gBS->CreateEvent (
478                  EVT_NOTIFY_WAIT,
479                  TPL_NOTIFY,
480                  Undi16SimpleNetworkWaitForPacket,
481                  &SimpleNetworkDevice->SimpleNetwork,
482                  &SimpleNetworkDevice->SimpleNetwork.WaitForPacket
483                  );
484  if (EFI_ERROR (Status)) {
485    DEBUG ((DEBUG_ERROR, "ERROR : Could not create event.  Status = %r\n", Status));
486    goto Done;
487  }
488  //
489  // Create an event to be signalled when ExitBootServices occurs in order
490  // to clean up nicely
491  //
492  Status = gBS->CreateEventEx (
493                  EVT_NOTIFY_SIGNAL,
494                  TPL_NOTIFY,
495                  Undi16SimpleNetworkEvent,
496                  NULL,
497                  &gEfiEventExitBootServicesGuid,
498                  &SimpleNetworkDevice->EfiBootEvent
499                  );
500  if (EFI_ERROR (Status)) {
501    DEBUG ((DEBUG_ERROR, "ERROR : Could not create event.  Status = %r\n", Status));
502    goto Done;
503  }
504
505  //
506  // Create an event to be signalled when Legacy Boot occurs to clean up the IVT
507  //
508  Status = EfiCreateEventLegacyBootEx(
509             TPL_NOTIFY,
510             Undi16SimpleNetworkEvent,
511             NULL,
512             &SimpleNetworkDevice->LegacyBootEvent
513             );
514
515  if (EFI_ERROR(Status)) {
516    DEBUG ((DEBUG_ERROR,"ERROR : Could not create event.  Status = %r\n",Status));
517    goto Done;
518  }
519
520  //
521  // Initialize the SimpleNetwork Mode Information
522  //
523  DEBUG ((DEBUG_NET, "Initialize Mode Information\n"));
524
525  SimpleNetworkDevice->SimpleNetworkMode.State                = EfiSimpleNetworkStopped;
526  SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize      = 14;
527  SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable = TRUE;
528  SimpleNetworkDevice->SimpleNetworkMode.MultipleTxSupported  = TRUE;
529  SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
530    EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
531    EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
532    EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS |
533    EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
534  SimpleNetworkDevice->SimpleNetworkMode.MaxMCastFilterCount = MAXNUM_MCADDR;
535
536  //
537  // Initialize the SimpleNetwork Private Information
538  //
539  DEBUG ((DEBUG_NET, "Initialize Private Information\n"));
540
541  Status = BiosSnp16AllocatePagesBelowOneMb (
542             sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1,
543             (VOID **) &SimpleNetworkDevice->Xmit
544             );
545  if (EFI_ERROR (Status)) {
546    goto Done;
547  }
548
549  Status = BiosSnp16AllocatePagesBelowOneMb (
550             1,
551             &SimpleNetworkDevice->TxRealModeMediaHeader
552             );
553  if (EFI_ERROR (Status)) {
554    goto Done;
555  }
556
557  Status = BiosSnp16AllocatePagesBelowOneMb (
558             1,
559             &SimpleNetworkDevice->TxRealModeDataBuffer
560             );
561  if (EFI_ERROR (Status)) {
562    goto Done;
563  }
564
565  Status = BiosSnp16AllocatePagesBelowOneMb (
566             1,
567             &SimpleNetworkDevice->TxDestAddr
568             );
569  if (EFI_ERROR (Status)) {
570    goto Done;
571  }
572
573  SimpleNetworkDevice->Xmit->XmitOffset               = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeMediaHeader) & 0x000f);
574
575  SimpleNetworkDevice->Xmit->XmitSegment              = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeMediaHeader) >> 4);
576
577  SimpleNetworkDevice->Xmit->DataBlkCount             = 1;
578
579  SimpleNetworkDevice->Xmit->DataBlock[0].TDPtrType   = 1;
580  SimpleNetworkDevice->Xmit->DataBlock[0].TDRsvdByte  = 0;
581
582  SimpleNetworkDevice->Xmit->DataBlock[0].TDDataPtrOffset = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeDataBuffer) & 0x000f);
583
584  SimpleNetworkDevice->Xmit->DataBlock[0].TDDataPtrSegment = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeDataBuffer) >> 4);
585
586  SimpleNetworkDevice->TxBufferFifo.First = 0;
587  SimpleNetworkDevice->TxBufferFifo.Last  = 0;
588
589  //
590  // Start() the SimpleNetwork device
591  //
592  DEBUG ((DEBUG_NET, "Start()\n"));
593
594  Status = Undi16SimpleNetworkStart (&SimpleNetworkDevice->SimpleNetwork);
595  if (EFI_ERROR (Status)) {
596    goto Done;
597  }
598  //
599  // GetInformation() the SimpleNetwork device
600  //
601  DEBUG ((DEBUG_NET, "GetInformation()\n"));
602
603  Status = Undi16SimpleNetworkGetInformation (&SimpleNetworkDevice->SimpleNetwork);
604  if (EFI_ERROR (Status)) {
605    goto Done;
606  }
607  //
608  // Build the device path for the child device
609  //
610  ZeroMem (&Node, sizeof (Node));
611  Node.DevPath.Type     = MESSAGING_DEVICE_PATH;
612  Node.DevPath.SubType  = MSG_MAC_ADDR_DP;
613  SetDevicePathNodeLength (&Node.DevPath, sizeof (MAC_ADDR_DEVICE_PATH));
614  CopyMem (
615    &Node.MacAddr.MacAddress,
616    &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
617    sizeof (EFI_MAC_ADDRESS)
618    );
619  SimpleNetworkDevice->DevicePath = AppendDevicePathNode (
620                                      SimpleNetworkDevice->BaseDevicePath,
621                                      &Node.DevPath
622                                      );
623
624  //
625  // GetNicType()  the SimpleNetwork device
626  //
627  DEBUG ((DEBUG_NET, "GetNicType()\n"));
628
629  Status = Undi16SimpleNetworkGetNicType (&SimpleNetworkDevice->SimpleNetwork);
630  if (EFI_ERROR (Status)) {
631    goto Done;
632  }
633  //
634  // GetNdisInfo() the SimpleNetwork device
635  //
636  DEBUG ((DEBUG_NET, "GetNdisInfo()\n"));
637
638  Status = Undi16SimpleNetworkGetNdisInfo (&SimpleNetworkDevice->SimpleNetwork);
639  if (EFI_ERROR (Status)) {
640    goto Done;
641  }
642  //
643  // Stop() the SimpleNetwork device
644  //
645  DEBUG ((DEBUG_NET, "Stop()\n"));
646
647  Status = SimpleNetworkDevice->SimpleNetwork.Stop (&SimpleNetworkDevice->SimpleNetwork);
648  if (EFI_ERROR (Status)) {
649    goto Done;
650  }
651  //
652  // Print Mode information
653  //
654  DEBUG ((DEBUG_NET, "Mode->State                = %d\n", SimpleNetworkDevice->SimpleNetworkMode.State));
655  DEBUG ((DEBUG_NET, "Mode->HwAddressSize        = %d\n", SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize));
656  DEBUG ((DEBUG_NET, "Mode->MacAddressChangeable = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable));
657  DEBUG ((DEBUG_NET, "Mode->MultiplTxSupported   = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MultipleTxSupported));
658  DEBUG ((DEBUG_NET, "Mode->NvRamSize            = %d\n", SimpleNetworkDevice->SimpleNetworkMode.NvRamSize));
659  DEBUG ((DEBUG_NET, "Mode->NvRamAccessSize      = %d\n", SimpleNetworkDevice->SimpleNetworkMode.NvRamAccessSize));
660  DEBUG ((DEBUG_NET, "Mode->ReceiveFilterSetting = %d\n", SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting));
661  DEBUG ((DEBUG_NET, "Mode->IfType               = %d\n", SimpleNetworkDevice->SimpleNetworkMode.IfType));
662  DEBUG ((DEBUG_NET, "Mode->MCastFilterCount     = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount));
663  for (Index = 0; Index < SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount; Index++) {
664    DEBUG ((DEBUG_NET, "  Filter[%02d] = ", Index));
665    for (Index2 = 0; Index2 < 16; Index2++) {
666      DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index].Addr[Index2]));
667    }
668
669    DEBUG ((DEBUG_NET, "\n"));
670  }
671
672  DEBUG ((DEBUG_NET, "CurrentAddress = "));
673  for (Index2 = 0; Index2 < 16; Index2++) {
674    DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress.Addr[Index2]));
675  }
676
677  DEBUG ((DEBUG_NET, "\n"));
678
679  DEBUG ((DEBUG_NET, "BroadcastAddress = "));
680  for (Index2 = 0; Index2 < 16; Index2++) {
681    DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress.Addr[Index2]));
682  }
683
684  DEBUG ((DEBUG_NET, "\n"));
685
686  DEBUG ((DEBUG_NET, "PermanentAddress = "));
687  for (Index2 = 0; Index2 < 16; Index2++) {
688    DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress.Addr[Index2]));
689  }
690
691  DEBUG ((DEBUG_NET, "\n"));
692
693  //
694  // The network device was started, information collected, and stopped.
695  // Install protocol interfaces for the SimpleNetwork device.
696  //
697  DEBUG ((DEBUG_NET, "Install Protocol Interfaces on network interface\n"));
698
699  Status = gBS->InstallMultipleProtocolInterfaces (
700                  &SimpleNetworkDevice->Handle,
701                  &gEfiSimpleNetworkProtocolGuid,
702                  &SimpleNetworkDevice->SimpleNetwork,
703                  &gEfiNetworkInterfaceIdentifierProtocolGuid,
704                  &SimpleNetworkDevice->Nii,
705                  &gEfiDevicePathProtocolGuid,
706                  SimpleNetworkDevice->DevicePath,
707                  NULL
708                  );
709  if (EFI_ERROR (Status)) {
710    goto Done;
711  }
712  //
713  // Open PCI I/O from the newly created child handle
714  //
715  Status = gBS->OpenProtocol (
716                  Controller,
717                  &gEfiPciIoProtocolGuid,
718                  (VOID **) &PciIo,
719                  This->DriverBindingHandle,
720                  SimpleNetworkDevice->Handle,
721                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
722                  );
723
724  DEBUG ((DEBUG_INIT, "UNDI16 Driver : EFI_SUCCESS\n"));
725
726Done:
727  if (EFI_ERROR (Status)) {
728    if (SimpleNetworkDevice != NULL) {
729
730      Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork);
731      //
732      // CLOSE + SHUTDOWN
733      //
734      Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice);
735      //
736      // CLEANUP
737      //
738      Undi16SimpleNetworkStopUndi (SimpleNetworkDevice);
739      //
740      // STOP
741      //
742      if (SimpleNetworkDevice->UndiLoaded) {
743        Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);
744      }
745
746      if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket != NULL) {
747        gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket);
748      }
749
750      if (SimpleNetworkDevice->LegacyBootEvent != NULL) {
751        gBS->CloseEvent (SimpleNetworkDevice->LegacyBootEvent);
752      }
753
754      if (SimpleNetworkDevice->EfiBootEvent != NULL) {
755        gBS->CloseEvent (SimpleNetworkDevice->EfiBootEvent);
756      }
757
758      if (SimpleNetworkDevice->Xmit != NULL) {
759        gBS->FreePages (
760               (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->Xmit,
761               sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1
762               );
763      }
764
765      if (SimpleNetworkDevice->TxRealModeMediaHeader != NULL) {
766        gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeMediaHeader, 1);
767      }
768
769      if (SimpleNetworkDevice->TxRealModeDataBuffer != NULL) {
770        gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeDataBuffer, 1);
771      }
772
773      if (SimpleNetworkDevice->TxDestAddr != NULL) {
774        gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxDestAddr, 1);
775      }
776
777      gBS->FreePool (SimpleNetworkDevice);
778
779      //
780      //  Only restore the vector if it was cached.
781      //
782      if (mCachedInt1A) {
783        RestoreCachedVectorAddress (0x1A);
784        mCachedInt1A = FALSE;
785      }
786    }
787
788    if (PciIo != NULL) {
789      Status = PciIo->Attributes (
790                        PciIo,
791                        EfiPciIoAttributeOperationSupported,
792                        0,
793                        &Supports
794                        );
795      if (!EFI_ERROR (Status)) {
796        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
797        Status = PciIo->Attributes (
798                          PciIo,
799                          EfiPciIoAttributeOperationDisable,
800                          Supports,
801                          NULL
802                          );
803      }
804    }
805
806    gBS->CloseProtocol (
807           Controller,
808           &gEfiPciIoProtocolGuid,
809           This->DriverBindingHandle,
810           Controller
811           );
812
813    gBS->CloseProtocol (
814           Controller,
815           &gEfiDevicePathProtocolGuid,
816           This->DriverBindingHandle,
817           Controller
818           );
819    if (Status != EFI_OUT_OF_RESOURCES) {
820      Status = EFI_DEVICE_ERROR;
821    }
822  }
823  return Status;
824}
825
826/**
827  Stops the device by given device controller.
828
829  @param This               A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
830  @param Controller         The handle of the controller to test.
831  @param NumberOfChildren   The number of child device handles in ChildHandleBuffer.
832  @param ChildHandleBuffer  An array of child handles to be freed. May be NULL if
833                            NumberOfChildren is 0.
834
835  @retval  EFI_SUCCESS      - The device was stopped.
836  @retval  EFI_DEVICE_ERROR - The device could not be stopped due to a device error.
837**/
838EFI_STATUS
839EFIAPI
840BiosSnp16DriverBindingStop (
841  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
842  IN  EFI_HANDLE                      Controller,
843  IN  UINTN                           NumberOfChildren,
844  IN  EFI_HANDLE                      *ChildHandleBuffer
845  )
846{
847  EFI_STATUS                  Status;
848  UINTN                       Index;
849  BOOLEAN                     AllChildrenStopped;
850  EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork;
851  EFI_SIMPLE_NETWORK_DEV      *SimpleNetworkDevice;
852  EFI_PCI_IO_PROTOCOL         *PciIo;
853  UINT64                      Supports;
854
855  //
856  // Complete all outstanding transactions to Controller.
857  // Don't allow any new transaction to Controller to be started.
858  //
859  if (NumberOfChildren == 0) {
860    //
861    // Close the bus driver
862    //
863    Status = gBS->OpenProtocol (
864                    Controller,
865                    &gEfiPciIoProtocolGuid,
866                    (VOID **) &PciIo,
867                    This->DriverBindingHandle,
868                    Controller,
869                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
870                    );
871    if (!EFI_ERROR (Status)) {
872      Status = PciIo->Attributes (
873                        PciIo,
874                        EfiPciIoAttributeOperationSupported,
875                        0,
876                        &Supports
877                        );
878      if (!EFI_ERROR (Status)) {
879        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
880        Status = PciIo->Attributes (
881                          PciIo,
882                          EfiPciIoAttributeOperationDisable,
883                          Supports,
884                          NULL
885                          );
886      }
887    }
888
889    Status = gBS->CloseProtocol (
890                    Controller,
891                    &gEfiPciIoProtocolGuid,
892                    This->DriverBindingHandle,
893                    Controller
894                    );
895
896    Status = gBS->CloseProtocol (
897                    Controller,
898                    &gEfiDevicePathProtocolGuid,
899                    This->DriverBindingHandle,
900                    Controller
901                    );
902
903    if (EFI_ERROR (Status)) {
904      Status = EFI_DEVICE_ERROR;
905    }
906    return Status;
907  }
908
909  AllChildrenStopped = TRUE;
910
911  for (Index = 0; Index < NumberOfChildren; Index++) {
912
913    Status = gBS->OpenProtocol (
914                    ChildHandleBuffer[Index],
915                    &gEfiSimpleNetworkProtocolGuid,
916                    (VOID **) &SimpleNetwork,
917                    This->DriverBindingHandle,
918                    Controller,
919                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
920                    );
921    if (!EFI_ERROR (Status)) {
922
923      SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SimpleNetwork);
924
925      Status = gBS->CloseProtocol (
926                      Controller,
927                      &gEfiPciIoProtocolGuid,
928                      This->DriverBindingHandle,
929                      ChildHandleBuffer[Index]
930                      );
931
932      Status = gBS->UninstallMultipleProtocolInterfaces (
933                      SimpleNetworkDevice->Handle,
934                      &gEfiSimpleNetworkProtocolGuid,
935                      &SimpleNetworkDevice->SimpleNetwork,
936                      &gEfiNetworkInterfaceIdentifierProtocolGuid,
937                      &SimpleNetworkDevice->Nii,
938                      &gEfiDevicePathProtocolGuid,
939                      SimpleNetworkDevice->DevicePath,
940                      NULL
941                      );
942      if (EFI_ERROR (Status)) {
943        gBS->OpenProtocol (
944               Controller,
945               &gEfiPciIoProtocolGuid,
946               (VOID **) &PciIo,
947               This->DriverBindingHandle,
948               ChildHandleBuffer[Index],
949               EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
950               );
951      } else {
952
953        Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork);
954        //
955        // CLOSE + SHUTDOWN
956        //
957        Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice);
958        //
959        // CLEANUP
960        //
961        Undi16SimpleNetworkStopUndi (SimpleNetworkDevice);
962        //
963        // STOP
964        //
965        if (SimpleNetworkDevice->UndiLoaded) {
966          Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);
967        }
968
969        if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket != NULL) {
970          gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket);
971        }
972
973        if (SimpleNetworkDevice->LegacyBootEvent != NULL) {
974          gBS->CloseEvent (SimpleNetworkDevice->LegacyBootEvent);
975        }
976
977        if (SimpleNetworkDevice->EfiBootEvent != NULL) {
978          gBS->CloseEvent (SimpleNetworkDevice->EfiBootEvent);
979        }
980
981        if (SimpleNetworkDevice->Xmit != NULL) {
982          gBS->FreePages (
983                 (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->Xmit,
984                 sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1
985                 );
986        }
987
988        if (SimpleNetworkDevice->TxRealModeMediaHeader != NULL) {
989          gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeMediaHeader, 1);
990        }
991
992        if (SimpleNetworkDevice->TxRealModeDataBuffer != NULL) {
993          gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeDataBuffer, 1);
994        }
995
996        if (SimpleNetworkDevice->TxDestAddr != NULL) {
997          gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxDestAddr, 1);
998        }
999
1000        gBS->FreePool (SimpleNetworkDevice);
1001      }
1002
1003    }
1004
1005    if (EFI_ERROR (Status)) {
1006      AllChildrenStopped = FALSE;
1007    }
1008  }
1009
1010  if (!AllChildrenStopped) {
1011    return EFI_DEVICE_ERROR;
1012  }
1013
1014  return EFI_SUCCESS;
1015}
1016
1017//
1018// FIFO Support Functions
1019//
1020/**
1021  Judge whether transmit FIFO is full.
1022
1023  @param Fifo Point to trasmit FIFO structure.
1024
1025  @return BOOLEAN whether transmit FIFO is full.
1026**/
1027BOOLEAN
1028SimpleNetworkTransmitFifoFull (
1029  EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo
1030  )
1031{
1032  if (((Fifo->Last + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE) == Fifo->First) {
1033    return TRUE;
1034  }
1035
1036  return FALSE;
1037}
1038
1039/**
1040  Judge whether transmit FIFO is empty.
1041
1042  @param Fifo Point to trasmit FIFO structure.
1043
1044  @return BOOLEAN whether transmit FIFO is empty.
1045**/
1046BOOLEAN
1047SimpleNetworkTransmitFifoEmpty (
1048  EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo
1049  )
1050{
1051  if (Fifo->Last == Fifo->First) {
1052    return TRUE;
1053  }
1054
1055  return FALSE;
1056}
1057
1058
1059/**
1060  Add data into transmit buffer.
1061
1062  @param Fifo Point to trasmit FIFO structure.
1063  @param Data The data point want to be added.
1064
1065  @retval EFI_OUT_OF_RESOURCES  FIFO is full
1066  @retval EFI_SUCCESS           Success operation.
1067**/
1068EFI_STATUS
1069SimpleNetworkTransmitFifoAdd (
1070  EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo,
1071  VOID                        *Data
1072  )
1073{
1074  if (SimpleNetworkTransmitFifoFull (Fifo)) {
1075    return EFI_OUT_OF_RESOURCES;
1076  }
1077
1078  Fifo->Data[Fifo->Last]  = Data;
1079  Fifo->Last              = (Fifo->Last + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE;
1080  return EFI_SUCCESS;
1081}
1082
1083/**
1084  Get a data and remove it from network transmit FIFO.
1085
1086  @param Fifo Point to trasmit FIFO structure.
1087  @param Data On return, point to the data point want to be got and removed.
1088
1089  @retval EFI_OUT_OF_RESOURCES network transmit buffer is empty.
1090  @retval EFI_SUCCESS           Success operation.
1091**/
1092EFI_STATUS
1093SimpleNetworkTransmitFifoRemove (
1094  EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo,
1095  VOID                        **Data
1096  )
1097{
1098  if (SimpleNetworkTransmitFifoEmpty (Fifo)) {
1099    return EFI_OUT_OF_RESOURCES;
1100  }
1101
1102  *Data       = Fifo->Data[Fifo->First];
1103  Fifo->First = (Fifo->First + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE;
1104  return EFI_SUCCESS;
1105}
1106
1107/**
1108  Get recive filter setting according to EFI mask value.
1109
1110  @param ReceiveFilterSetting  filter setting EFI mask value.
1111
1112  @return UINT16 Undi filter setting value.
1113**/
1114UINT16
1115Undi16GetPacketFilterSetting (
1116  UINTN ReceiveFilterSetting
1117  )
1118{
1119  UINT16  PktFilter;
1120
1121  PktFilter = 0;
1122  if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) {
1123    PktFilter |= FLTR_DIRECTED;
1124  }
1125
1126  if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
1127    PktFilter |= FLTR_DIRECTED;
1128  }
1129
1130  if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {
1131    PktFilter |= FLTR_BRDCST;
1132  }
1133
1134  if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
1135    PktFilter |= FLTR_PRMSCS;
1136  }
1137
1138  if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
1139    PktFilter |= FLTR_PRMSCS;
1140    //
1141    // @bug : Do not know if this is right????
1142    //
1143  }
1144  //
1145  // @bug : What is FLTR_SRC_RTG?
1146  //
1147  return PktFilter;
1148}
1149
1150/**
1151  Get filter setting from multi cast buffer .
1152
1153  @param Mode           Point to mode structure.
1154  @param McastBuffer    The multi cast buffer
1155  @param HwAddressSize  Size of filter value.
1156
1157**/
1158VOID
1159Undi16GetMCastFilters (
1160  IN EFI_SIMPLE_NETWORK_MODE      *Mode,
1161  IN OUT PXENV_UNDI_MCAST_ADDR_T  *McastBuffer,
1162  IN UINTN                        HwAddressSize
1163  )
1164{
1165  UINTN Index;
1166
1167  //
1168  // @bug : What if Mode->MCastFilterCount > MAXNUM_MCADDR?
1169  //
1170  McastBuffer->MCastAddrCount = (UINT16) Mode->MCastFilterCount;
1171  for (Index = 0; Index < MAXNUM_MCADDR; Index++) {
1172    if (Index < McastBuffer->MCastAddrCount) {
1173      CopyMem (&McastBuffer->MCastAddr[Index], &Mode->MCastFilter[Index], HwAddressSize);
1174    } else {
1175      ZeroMem (&McastBuffer->MCastAddr[Index], HwAddressSize);
1176    }
1177  }
1178}
1179//
1180// Load 16 bit UNDI Option ROM into memory
1181//
1182/**
1183  Loads the undi driver.
1184
1185  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
1186
1187  @retval   EFI_SUCCESS   - Successfully loads undi driver.
1188  @retval   EFI_NOT_FOUND - Doesn't find undi driver or undi driver load failure.
1189**/
1190EFI_STATUS
1191Undi16SimpleNetworkLoadUndi (
1192  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
1193  )
1194{
1195  EFI_STATUS                Status;
1196  EFI_PCI_IO_PROTOCOL       *PciIo;
1197  UINTN                     RomAddress;
1198  PCI_EXPANSION_ROM_HEADER  *PciExpansionRomHeader;
1199  PCI_DATA_STRUCTURE        *PciDataStructure;
1200  PCI_TYPE00                Pci;
1201
1202  if (!mCachedInt1A) {
1203    Status = CacheVectorAddress (0x1A);
1204    if (!EFI_ERROR (Status)) {
1205      mCachedInt1A = TRUE;
1206    }
1207  }
1208
1209  PciIo = SimpleNetworkDevice->PciIo;
1210
1211  PciIo->Pci.Read (
1212               PciIo,
1213               EfiPciIoWidthUint32,
1214               0,
1215               sizeof (Pci) / sizeof (UINT32),
1216               &Pci
1217               );
1218
1219  for (RomAddress = 0xc0000; RomAddress < 0xfffff; RomAddress += 0x800) {
1220
1221    PciExpansionRomHeader = (PCI_EXPANSION_ROM_HEADER *) RomAddress;
1222
1223    if (PciExpansionRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
1224      continue;
1225    }
1226
1227    DEBUG ((DEBUG_INIT, "Option ROM found at %X\n", RomAddress));
1228
1229    //
1230    // If the pointer to the PCI Data Structure is invalid, no further images can be located.
1231    // The PCI Data Structure must be DWORD aligned.
1232    //
1233    if (PciExpansionRomHeader->PcirOffset == 0 ||
1234        (PciExpansionRomHeader->PcirOffset & 3) != 0 ||
1235        RomAddress + PciExpansionRomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > 0x100000) {
1236      break;
1237    }
1238
1239    PciDataStructure = (PCI_DATA_STRUCTURE *) (RomAddress + PciExpansionRomHeader->PcirOffset);
1240
1241    if (PciDataStructure->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
1242      continue;
1243    }
1244
1245    DEBUG ((DEBUG_INIT, "PCI Data Structure found at %X\n", PciDataStructure));
1246
1247    if (PciDataStructure->VendorId != Pci.Hdr.VendorId || PciDataStructure->DeviceId != Pci.Hdr.DeviceId) {
1248      continue;
1249    }
1250
1251    DEBUG (
1252        (DEBUG_INIT,
1253         "PCI device with matchinng VendorId and DeviceId (%d,%d)\n",
1254         (UINTN) PciDataStructure->VendorId,
1255         (UINTN) PciDataStructure->DeviceId)
1256        );
1257
1258    Status = LaunchBaseCode (SimpleNetworkDevice, RomAddress);
1259
1260    if (!EFI_ERROR (Status)) {
1261      return EFI_SUCCESS;
1262    }
1263
1264    //
1265    // Free resources allocated in LaunchBaseCode
1266    //
1267    Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);
1268  }
1269
1270  return EFI_NOT_FOUND;
1271}
1272
1273/**
1274  Unload 16 bit UNDI Option ROM from memory
1275
1276  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
1277
1278  @return EFI_STATUS
1279**/
1280EFI_STATUS
1281Undi16SimpleNetworkUnloadUndi (
1282  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
1283  )
1284{
1285  if (SimpleNetworkDevice->UndiLoaderTable != NULL) {
1286    ZeroMem (SimpleNetworkDevice->UndiLoaderTable, SimpleNetworkDevice->UndiLoaderTablePages << EFI_PAGE_SHIFT);
1287    gBS->FreePages (
1288          (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->UndiLoaderTable,
1289          SimpleNetworkDevice->UndiLoaderTablePages
1290          );
1291  }
1292
1293  if (SimpleNetworkDevice->DestinationDataSegment != NULL) {
1294    ZeroMem (
1295      SimpleNetworkDevice->DestinationDataSegment,
1296      SimpleNetworkDevice->DestinationDataSegmentPages << EFI_PAGE_SHIFT
1297      );
1298    gBS->FreePages (
1299          (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationDataSegment,
1300          SimpleNetworkDevice->DestinationDataSegmentPages
1301          );
1302  }
1303
1304  if (SimpleNetworkDevice->DestinationStackSegment != NULL) {
1305    ZeroMem (
1306      SimpleNetworkDevice->DestinationStackSegment,
1307      SimpleNetworkDevice->DestinationStackSegmentPages << EFI_PAGE_SHIFT
1308      );
1309    gBS->FreePages (
1310          (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationStackSegment,
1311          SimpleNetworkDevice->DestinationStackSegmentPages
1312          );
1313  }
1314
1315  if (SimpleNetworkDevice->DestinationCodeSegment != NULL) {
1316    ZeroMem (
1317      SimpleNetworkDevice->DestinationCodeSegment,
1318      SimpleNetworkDevice->DestinationCodeSegmentPages << EFI_PAGE_SHIFT
1319      );
1320    gBS->FreePages (
1321          (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationCodeSegment,
1322          SimpleNetworkDevice->DestinationCodeSegmentPages
1323          );
1324  }
1325
1326  return EFI_SUCCESS;
1327}
1328
1329/**
1330  Start the UNDI interface.
1331
1332  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
1333  @param Ax                  PCI address of Undi device.
1334
1335  @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM.
1336  @retval Others           Status of start 16 bit UNDI ROM.
1337**/
1338EFI_STATUS
1339Undi16SimpleNetworkStartUndi (
1340  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice,
1341  UINT16                  Ax
1342  )
1343{
1344  EFI_STATUS          Status;
1345  PXENV_START_UNDI_T  Start;
1346
1347  //
1348  // Call 16 bit UNDI ROM to start the network interface
1349  //
1350  //
1351  // @bug : What is this state supposed to be???
1352  //
1353  Start.Status  = INIT_PXE_STATUS;
1354  Start.Ax      = Ax;
1355  Start.Bx      = 0x0000;
1356  Start.Dx      = 0x0000;
1357  Start.Di      = 0x0000;
1358  Start.Es      = 0x0000;
1359
1360  Status        = PxeStartUndi (SimpleNetworkDevice, &Start);
1361  if (EFI_ERROR (Status)) {
1362    return Status;
1363  }
1364  //
1365  // Check the status code from the 16 bit UNDI ROM
1366  //
1367  if (Start.Status != PXENV_STATUS_SUCCESS) {
1368    return EFI_DEVICE_ERROR;
1369  }
1370
1371  return Status;
1372}
1373
1374
1375/**
1376  Stop the UNDI interface
1377
1378  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
1379
1380  @retval EFI_DEVICE_ERROR Fail to stop 16 bit UNDI ROM.
1381  @retval Others           Status of stop 16 bit UNDI ROM.
1382**/
1383EFI_STATUS
1384Undi16SimpleNetworkStopUndi (
1385  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
1386  )
1387{
1388  EFI_STATUS        Status;
1389  PXENV_STOP_UNDI_T Stop;
1390
1391  //
1392  // Call 16 bit UNDI ROM to start the network interface
1393  //
1394  Stop.Status = INIT_PXE_STATUS;
1395
1396  Status      = PxeUndiStop (SimpleNetworkDevice, &Stop);
1397  if (EFI_ERROR (Status)) {
1398    return Status;
1399  }
1400  //
1401  // Check the status code from the 16 bit UNDI ROM
1402  //
1403  if (Stop.Status != PXENV_STATUS_SUCCESS) {
1404    return EFI_DEVICE_ERROR;
1405  }
1406
1407  return Status;
1408}
1409
1410/**
1411  Cleanup Unid network interface
1412
1413  @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
1414
1415  @retval EFI_DEVICE_ERROR Fail to cleanup 16 bit UNDI ROM.
1416  @retval Others           Status of cleanup 16 bit UNDI ROM.
1417**/
1418EFI_STATUS
1419Undi16SimpleNetworkCleanupUndi (
1420  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
1421  )
1422{
1423  EFI_STATUS            Status;
1424  PXENV_UNDI_CLEANUP_T  Cleanup;
1425
1426  //
1427  // Call 16 bit UNDI ROM to cleanup the network interface
1428  //
1429  Cleanup.Status  = INIT_PXE_STATUS;
1430
1431  Status          = PxeUndiCleanup (SimpleNetworkDevice, &Cleanup);
1432  if (EFI_ERROR (Status)) {
1433    return Status;
1434  }
1435  //
1436  // Check the status code from the 16 bit UNDI ROM
1437  //
1438  if (Cleanup.Status != PXENV_STATUS_SUCCESS) {
1439    return EFI_DEVICE_ERROR;
1440  }
1441
1442  return Status;
1443}
1444
1445/**
1446  Get runtime information for Undi network interface
1447
1448  @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
1449
1450  @retval EFI_SUCCESS Sucess operation.
1451  @retval Others      Fail to get runtime information for Undi network interface.
1452**/
1453EFI_STATUS
1454Undi16SimpleNetworkGetInformation (
1455  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
1456  )
1457{
1458  EFI_STATUS              Status;
1459  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
1460  UINTN                   Index;
1461
1462  if (This == NULL) {
1463    return EFI_INVALID_PARAMETER;
1464  }
1465
1466  Status              = EFI_SUCCESS;
1467  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
1468
1469  if (SimpleNetworkDevice == NULL) {
1470    return EFI_DEVICE_ERROR;
1471  }
1472  //
1473  // Verify that the current state of the adapter is valid for this call.
1474  //
1475  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
1476  case EfiSimpleNetworkStarted:
1477  case EfiSimpleNetworkInitialized:
1478    break;
1479
1480  case EfiSimpleNetworkStopped:
1481    return EFI_NOT_STARTED;
1482
1483  default:
1484    return EFI_DEVICE_ERROR;
1485  }
1486  //
1487  // Call 16 bit UNDI ROM to start the network interface
1488  //
1489  ZeroMem (&SimpleNetworkDevice->GetInformation, sizeof (PXENV_UNDI_GET_INFORMATION_T));
1490
1491  SimpleNetworkDevice->GetInformation.Status  = INIT_PXE_STATUS;
1492
1493  Status = PxeUndiGetInformation (SimpleNetworkDevice, &SimpleNetworkDevice->GetInformation);
1494  if (EFI_ERROR (Status)) {
1495    return Status;
1496  }
1497
1498  DEBUG ((DEBUG_NET, "  GetInformation.Status      = %d\n", SimpleNetworkDevice->GetInformation.Status));
1499  DEBUG ((DEBUG_NET, "  GetInformation.BaseIo      = %d\n", SimpleNetworkDevice->GetInformation.BaseIo));
1500  DEBUG ((DEBUG_NET, "  GetInformation.IntNumber   = %d\n", SimpleNetworkDevice->GetInformation.IntNumber));
1501  DEBUG ((DEBUG_NET, "  GetInformation.MaxTranUnit = %d\n", SimpleNetworkDevice->GetInformation.MaxTranUnit));
1502  DEBUG ((DEBUG_NET, "  GetInformation.HwType      = %d\n", SimpleNetworkDevice->GetInformation.HwType));
1503  DEBUG ((DEBUG_NET, "  GetInformation.HwAddrLen   = %d\n", SimpleNetworkDevice->GetInformation.HwAddrLen));
1504  DEBUG ((DEBUG_NET, "  GetInformation.ROMAddress  = %d\n", SimpleNetworkDevice->GetInformation.ROMAddress));
1505  DEBUG ((DEBUG_NET, "  GetInformation.RxBufCt     = %d\n", SimpleNetworkDevice->GetInformation.RxBufCt));
1506  DEBUG ((DEBUG_NET, "  GetInformation.TxBufCt     = %d\n", SimpleNetworkDevice->GetInformation.TxBufCt));
1507
1508  DEBUG ((DEBUG_NET, "  GetInformation.CurNodeAddr ="));
1509  for (Index = 0; Index < 16; Index++) {
1510    DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->GetInformation.CurrentNodeAddress[Index]));
1511  }
1512
1513  DEBUG ((DEBUG_NET, "\n"));
1514
1515  DEBUG ((DEBUG_NET, "  GetInformation.PermNodeAddr ="));
1516  for (Index = 0; Index < 16; Index++) {
1517    DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->GetInformation.PermNodeAddress[Index]));
1518  }
1519
1520  DEBUG ((DEBUG_NET, "\n"));
1521
1522  //
1523  // Check the status code from the 16 bit UNDI ROM
1524  //
1525  if (SimpleNetworkDevice->GetInformation.Status != PXENV_STATUS_SUCCESS) {
1526    return EFI_DEVICE_ERROR;
1527  }
1528  //
1529  // The information has been retrieved.  Fill in Mode data.
1530  //
1531  SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize  = SimpleNetworkDevice->GetInformation.HwAddrLen;
1532
1533  SimpleNetworkDevice->SimpleNetworkMode.MaxPacketSize  = SimpleNetworkDevice->GetInformation.MaxTranUnit;
1534
1535  SimpleNetworkDevice->SimpleNetworkMode.IfType         = (UINT8) SimpleNetworkDevice->GetInformation.HwType;
1536
1537  ZeroMem (
1538    &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
1539    sizeof SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress
1540    );
1541
1542  CopyMem (
1543    &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
1544    &SimpleNetworkDevice->GetInformation.CurrentNodeAddress,
1545    SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
1546    );
1547
1548  ZeroMem (
1549    &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
1550    sizeof SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress
1551    );
1552
1553  CopyMem (
1554    &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
1555    &SimpleNetworkDevice->GetInformation.PermNodeAddress,
1556    SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
1557    );
1558
1559  //
1560  // hard code broadcast address - not avail in PXE2.1
1561  //
1562  ZeroMem (
1563    &SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress,
1564    sizeof SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress
1565    );
1566
1567  SetMem (
1568    &SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress,
1569    SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize,
1570    0xff
1571    );
1572
1573  return Status;
1574}
1575
1576/**
1577  Get NIC type
1578
1579  @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
1580
1581  @retval EFI_SUCCESS Sucess operation.
1582  @retval Others      Fail to get NIC type.
1583**/
1584EFI_STATUS
1585Undi16SimpleNetworkGetNicType (
1586  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
1587  )
1588{
1589  EFI_STATUS              Status;
1590  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
1591
1592  if (This == NULL) {
1593    return EFI_INVALID_PARAMETER;
1594  }
1595
1596  Status              = EFI_SUCCESS;
1597  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
1598
1599  if (SimpleNetworkDevice == NULL) {
1600    return EFI_DEVICE_ERROR;
1601  }
1602
1603  ZeroMem (&SimpleNetworkDevice->GetNicType, sizeof (PXENV_UNDI_GET_NIC_TYPE_T));
1604
1605  SimpleNetworkDevice->GetNicType.Status  = INIT_PXE_STATUS;
1606
1607  Status = PxeUndiGetNicType (SimpleNetworkDevice, &SimpleNetworkDevice->GetNicType);
1608
1609  if (EFI_ERROR (Status)) {
1610    return Status;
1611  }
1612
1613  DEBUG ((DEBUG_NET, "  GetNicType.Status      = %d\n", SimpleNetworkDevice->GetNicType.Status));
1614  DEBUG ((DEBUG_NET, "  GetNicType.NicType     = %d\n", SimpleNetworkDevice->GetNicType.NicType));
1615  //
1616  // Check the status code from the 16 bit UNDI ROM
1617  //
1618  if (SimpleNetworkDevice->GetNicType.Status != PXENV_STATUS_SUCCESS) {
1619    return EFI_DEVICE_ERROR;
1620  }
1621  //
1622  // The information has been retrieved.  Fill in Mode data.
1623  //
1624  return Status;
1625}
1626
1627/**
1628  Get NDIS information
1629
1630  @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
1631
1632  @retval EFI_SUCCESS Sucess operation.
1633  @retval Others      Fail to get NDIS information.
1634**/
1635EFI_STATUS
1636Undi16SimpleNetworkGetNdisInfo (
1637  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
1638  )
1639{
1640  EFI_STATUS              Status;
1641  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
1642
1643  if (This == NULL) {
1644    return EFI_INVALID_PARAMETER;
1645  }
1646
1647  Status              = EFI_SUCCESS;
1648  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
1649
1650  if (SimpleNetworkDevice == NULL) {
1651    return EFI_DEVICE_ERROR;
1652  }
1653
1654  ZeroMem (&SimpleNetworkDevice->GetNdisInfo, sizeof (PXENV_UNDI_GET_NDIS_INFO_T));
1655
1656  SimpleNetworkDevice->GetNdisInfo.Status = INIT_PXE_STATUS;
1657
1658  Status = PxeUndiGetNdisInfo (SimpleNetworkDevice, &SimpleNetworkDevice->GetNdisInfo);
1659
1660  if (EFI_ERROR (Status)) {
1661    return Status;
1662  }
1663
1664  DEBUG ((DEBUG_NET, "  GetNdisInfo.Status       = %d\n", SimpleNetworkDevice->GetNdisInfo.Status));
1665  DEBUG ((DEBUG_NET, "  GetNdisInfo.IfaceType    = %a\n", SimpleNetworkDevice->GetNdisInfo.IfaceType));
1666  DEBUG ((DEBUG_NET, "  GetNdisInfo.LinkSpeed    = %d\n", SimpleNetworkDevice->GetNdisInfo.LinkSpeed));
1667  DEBUG ((DEBUG_NET, "  GetNdisInfo.ServiceFlags = %08x\n", SimpleNetworkDevice->GetNdisInfo.ServiceFlags));
1668
1669  //
1670  // Check the status code from the 16 bit UNDI ROM
1671  //
1672  if (SimpleNetworkDevice->GetNdisInfo.Status != PXENV_STATUS_SUCCESS) {
1673    return EFI_DEVICE_ERROR;
1674  }
1675  //
1676  // The information has been retrieved.  Fill in Mode data.
1677  //
1678  return Status;
1679}
1680
1681/**
1682  Call Undi ROM 16bit ISR() to check interrupt cause.
1683
1684  @param This               A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
1685  @param FrameLength        The length of frame buffer.
1686  @param FrameHeaderLength  The length of frame buffer's header if has.
1687  @param Frame              The frame buffer to process network interrupt.
1688  @param ProtType           The type network transmit protocol
1689  @param PktType            The type of package.
1690
1691  @retval EFI_DEVICE_ERROR  Fail to execute 16 bit ROM's ISR, or status is invalid.
1692  @retval EFI_SUCCESS       Success operation.
1693**/
1694EFI_STATUS
1695Undi16SimpleNetworkIsr (
1696  IN EFI_SIMPLE_NETWORK_PROTOCOL * This,
1697  IN UINTN                       *FrameLength,
1698  IN UINTN                       *FrameHeaderLength, OPTIONAL
1699  IN UINT8                       *Frame, OPTIONAL
1700  IN UINT8                       *ProtType, OPTIONAL
1701  IN UINT8                       *PktType OPTIONAL
1702  )
1703{
1704  EFI_STATUS              Status;
1705  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
1706  BOOLEAN                 FrameReceived;
1707
1708  if (This == NULL) {
1709    return EFI_INVALID_PARAMETER;
1710  }
1711
1712  Status              = EFI_SUCCESS;
1713  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
1714
1715  if (SimpleNetworkDevice == NULL) {
1716    return EFI_DEVICE_ERROR;
1717  }
1718
1719  FrameReceived = FALSE;
1720
1721  //
1722  // Verify that the current state of the adapter is valid for this call.
1723  //
1724  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
1725  case EfiSimpleNetworkInitialized:
1726    break;
1727
1728  case EfiSimpleNetworkStopped:
1729    return EFI_NOT_STARTED;
1730
1731  case EfiSimpleNetworkStarted:
1732  default:
1733    return EFI_DEVICE_ERROR;
1734  }
1735
1736  DEBUG ((DEBUG_NET, "Isr() IsrValid = %d\n", SimpleNetworkDevice->IsrValid));
1737
1738  if (!SimpleNetworkDevice->IsrValid) {
1739    //
1740    // Call 16 bit UNDI ROM to open the network interface
1741    //
1742    ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));
1743    SimpleNetworkDevice->Isr.Status   = INIT_PXE_STATUS;
1744    SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_START;
1745
1746    DEBUG ((DEBUG_NET, "Isr() START\n"));
1747
1748    Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
1749    if (EFI_ERROR (Status)) {
1750      return Status;
1751    }
1752    //
1753    // Check the status code from the 16 bit UNDI ROM
1754    //
1755    if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
1756      return EFI_DEVICE_ERROR;
1757    }
1758    //
1759    // There have been no events on this UNDI interface, so return EFI_NOT_READY
1760    //
1761    if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_NOT_OURS) {
1762      return EFI_SUCCESS;
1763    }
1764    //
1765    // There is data to process, so call until all events processed.
1766    //
1767    ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));
1768    SimpleNetworkDevice->Isr.Status   = INIT_PXE_STATUS;
1769    SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
1770
1771    DEBUG ((DEBUG_NET, "Isr() PROCESS\n"));
1772
1773    Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
1774    if (EFI_ERROR (Status)) {
1775      return Status;
1776    }
1777
1778    SimpleNetworkDevice->IsrValid = TRUE;
1779  }
1780  //
1781  // Call UNDI GET_NEXT until DONE
1782  //
1783  while (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_DONE) {
1784    //
1785    // Check the status code from the 16 bit UNDI ROM
1786    //
1787    if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
1788      return EFI_DEVICE_ERROR;
1789    }
1790    //
1791    // UNDI is busy.  Caller will have to call again.
1792    // This should never happen with a polled mode driver.
1793    //
1794    if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_BUSY) {
1795      DEBUG ((DEBUG_NET, "  BUSY\n"));
1796      return EFI_SUCCESS;
1797    }
1798    //
1799    // Check for invalud UNDI FuncFlag
1800    //
1801    if (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_RECEIVE &&
1802        SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_TRANSMIT
1803        ) {
1804      DEBUG ((DEBUG_NET, "  Invalid SimpleNetworkDevice->Isr.FuncFlag value %d\n", SimpleNetworkDevice->Isr.FuncFlag));
1805      return EFI_DEVICE_ERROR;
1806    }
1807    //
1808    // Check for Transmit Event
1809    //
1810    if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_TRANSMIT) {
1811      DEBUG ((DEBUG_NET, "  TRANSMIT\n"));
1812      SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
1813    }
1814    //
1815    // Check for Receive Event
1816    //
1817    else if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_RECEIVE) {
1818      //
1819      // note - this code will hang on a receive interrupt in a GetStatus loop
1820      //
1821      DEBUG ((DEBUG_NET, "  RECEIVE\n"));
1822      SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
1823
1824      DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.BufferLength      = %d\n", SimpleNetworkDevice->Isr.BufferLength));
1825      DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.FrameLength       = %d\n", SimpleNetworkDevice->Isr.FrameLength));
1826      DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.FrameHeaderLength = %d\n", SimpleNetworkDevice->Isr.FrameHeaderLength));
1827      DEBUG (
1828        (
1829        DEBUG_NET, "SimpleNetworkDevice->Isr.Frame             = %04x:%04x\n", SimpleNetworkDevice->Isr.FrameSegSel,
1830        SimpleNetworkDevice->Isr.FrameOffset
1831        )
1832        );
1833      DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.ProtType          = 0x%02x\n", SimpleNetworkDevice->Isr.BufferLength));
1834      DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.PktType           = 0x%02x\n", SimpleNetworkDevice->Isr.BufferLength));
1835
1836      if (FrameReceived) {
1837        return EFI_SUCCESS;
1838      }
1839
1840      if ((Frame == NULL) || (SimpleNetworkDevice->Isr.FrameLength > *FrameLength)) {
1841        DEBUG ((DEBUG_NET, "return EFI_BUFFER_TOO_SMALL   *FrameLength = %08x\n", *FrameLength));
1842        *FrameLength = SimpleNetworkDevice->Isr.FrameLength;
1843        return EFI_BUFFER_TOO_SMALL;
1844      }
1845
1846      *FrameLength = SimpleNetworkDevice->Isr.FrameLength;
1847      if (FrameHeaderLength != NULL) {
1848        *FrameHeaderLength = SimpleNetworkDevice->Isr.FrameHeaderLength;
1849      }
1850
1851      if (ProtType != NULL) {
1852        *ProtType = SimpleNetworkDevice->Isr.ProtType;
1853      }
1854
1855      if (PktType != NULL) {
1856        *PktType = SimpleNetworkDevice->Isr.PktType;
1857      }
1858
1859      CopyMem (
1860        Frame,
1861        (VOID *)(UINTN) ((SimpleNetworkDevice->Isr.FrameSegSel << 4) + SimpleNetworkDevice->Isr.FrameOffset),
1862        SimpleNetworkDevice->Isr.BufferLength
1863        );
1864      Frame = Frame + SimpleNetworkDevice->Isr.BufferLength;
1865      if (SimpleNetworkDevice->Isr.BufferLength == SimpleNetworkDevice->Isr.FrameLength) {
1866        FrameReceived = TRUE;
1867      }
1868    }
1869    //
1870    // There is data to process, so call until all events processed.
1871    //
1872    ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));
1873    SimpleNetworkDevice->Isr.Status   = INIT_PXE_STATUS;
1874    SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
1875
1876    DEBUG ((DEBUG_NET, "Isr() GET NEXT\n"));
1877
1878    Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
1879    if (EFI_ERROR (Status)) {
1880      return Status;
1881    }
1882    //
1883    // Check the status code from the 16 bit UNDI ROM
1884    //
1885    //        if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
1886    //            return EFI_DEVICE_ERROR;
1887    //        }
1888    //
1889  }
1890
1891  SimpleNetworkDevice->IsrValid = FALSE;
1892  return EFI_SUCCESS;
1893}
1894//
1895// ///////////////////////////////////////////////////////////////////////////////////////
1896// Simple Network Protocol Interface Functions using 16 bit UNDI Option ROMs
1897/////////////////////////////////////////////////////////////////////////////////////////
1898//
1899// Start()
1900//
1901/**
1902  Call 16 bit UNDI ROM to start the network interface
1903
1904  @param This       A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
1905
1906  @retval EFI_DEVICE_ERROR Network interface has not be initialized.
1907  @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.
1908  @retval EFI_SUCESS       Success operation.
1909**/
1910EFI_STATUS
1911EFIAPI
1912Undi16SimpleNetworkStart (
1913  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
1914  )
1915{
1916  EFI_STATUS              Status;
1917  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
1918  PXENV_UNDI_STARTUP_T    Startup;
1919
1920  if (This == NULL) {
1921    return EFI_INVALID_PARAMETER;
1922  }
1923
1924  Status              = EFI_SUCCESS;
1925  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
1926
1927  if (SimpleNetworkDevice == NULL) {
1928    return EFI_DEVICE_ERROR;
1929  }
1930  //
1931  // Verify that the current state of the adapter is valid for this call.
1932  //
1933  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
1934  case EfiSimpleNetworkStopped:
1935    break;
1936
1937  case EfiSimpleNetworkStarted:
1938  case EfiSimpleNetworkInitialized:
1939    return EFI_ALREADY_STARTED;
1940
1941  default:
1942    return EFI_DEVICE_ERROR;
1943  }
1944  //
1945  // Call 16 bit UNDI ROM to start the network interface
1946  //
1947  Startup.Status  = INIT_PXE_STATUS;
1948
1949  Status          = PxeUndiStartup (SimpleNetworkDevice, &Startup);
1950  if (EFI_ERROR (Status)) {
1951    return Status;
1952  }
1953  //
1954  // Check the status code from the 16 bit UNDI ROM
1955  //
1956  if (Startup.Status != PXENV_STATUS_SUCCESS) {
1957    return EFI_DEVICE_ERROR;
1958  }
1959  //
1960  // The UNDI interface has been started, so update the State.
1961  //
1962  SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStarted;
1963
1964  //
1965  //
1966  //
1967  SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting = 0;
1968  SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount     = 0;
1969
1970  return Status;
1971}
1972//
1973// Stop()
1974//
1975/**
1976  Call 16 bit UNDI ROM to stop the network interface
1977
1978  @param This       A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
1979
1980  @retval EFI_DEVICE_ERROR Network interface has not be initialized.
1981  @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.
1982  @retval EFI_SUCESS       Success operation.
1983**/
1984EFI_STATUS
1985EFIAPI
1986Undi16SimpleNetworkStop (
1987  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
1988  )
1989{
1990  EFI_STATUS              Status;
1991  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
1992
1993  if (This == NULL) {
1994    return EFI_INVALID_PARAMETER;
1995  }
1996
1997  Status              = EFI_SUCCESS;
1998  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
1999
2000  if (SimpleNetworkDevice == NULL) {
2001    return EFI_DEVICE_ERROR;
2002  }
2003  //
2004  // Verify that the current state of the adapter is valid for this call.
2005  //
2006  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
2007  case EfiSimpleNetworkStarted:
2008    break;
2009
2010  case EfiSimpleNetworkStopped:
2011    return EFI_NOT_STARTED;
2012
2013  case EfiSimpleNetworkInitialized:
2014  default:
2015    return EFI_DEVICE_ERROR;
2016  }
2017
2018  SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStopped;
2019
2020  return Status;
2021}
2022
2023//
2024// Initialize()
2025//
2026/**
2027  Initialize network interface
2028
2029  @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
2030  @param ExtraRxBufferSize    The size of extra request receive buffer.
2031  @param ExtraTxBufferSize    The size of extra request transmit buffer.
2032
2033  @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.
2034  @retval EFI_SUCESS       Success operation.
2035**/
2036EFI_STATUS
2037EFIAPI
2038Undi16SimpleNetworkInitialize (
2039  IN EFI_SIMPLE_NETWORK_PROTOCOL            *This,
2040  IN UINTN                                  ExtraRxBufferSize  OPTIONAL,
2041  IN UINTN                                  ExtraTxBufferSize  OPTIONAL
2042  )
2043{
2044  EFI_STATUS              Status;
2045  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
2046  PXENV_UNDI_INITIALIZE_T Initialize;
2047  PXENV_UNDI_OPEN_T       Open;
2048
2049  if (This == NULL) {
2050    return EFI_INVALID_PARAMETER;
2051  }
2052
2053  Status              = EFI_SUCCESS;
2054  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
2055
2056  if (SimpleNetworkDevice == NULL) {
2057    return EFI_DEVICE_ERROR;
2058  }
2059  //
2060  // Verify that the current state of the adapter is valid for this call.
2061  //
2062  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
2063  case EfiSimpleNetworkStopped:
2064    return EFI_NOT_STARTED;
2065
2066  case EfiSimpleNetworkStarted:
2067    break;
2068
2069  case EfiSimpleNetworkInitialized:
2070  default:
2071    return EFI_DEVICE_ERROR;
2072  }
2073  //
2074  // Call 16 bit UNDI ROM to start the network interface
2075  //
2076  Initialize.Status       = INIT_PXE_STATUS;
2077  Initialize.ProtocolIni  = 0;
2078
2079  Status                  = PxeUndiInitialize (SimpleNetworkDevice, &Initialize);
2080
2081  if (EFI_ERROR (Status)) {
2082    DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiInitialize() - Status = %r\n", Status));
2083    DEBUG ((DEBUG_ERROR, "Initialize.Status == %xh\n", Initialize.Status));
2084
2085    if (Initialize.Status == PXENV_STATUS_UNDI_MEDIATEST_FAILED) {
2086      Status = EFI_NO_MEDIA;
2087    }
2088
2089    return Status;
2090  }
2091  //
2092  // Check the status code from the 16 bit UNDI ROM
2093  //
2094  if (Initialize.Status != PXENV_STATUS_SUCCESS) {
2095    DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiInitialize() - Initialize.Status = %04x\n", Initialize.Status));
2096    return EFI_DEVICE_ERROR;
2097  }
2098  //
2099  // Call 16 bit UNDI ROM to open the network interface
2100  //
2101  Open.Status     = INIT_PXE_STATUS;
2102  Open.OpenFlag   = 0;
2103  Open.PktFilter  = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);
2104  Undi16GetMCastFilters (
2105    &SimpleNetworkDevice->SimpleNetworkMode,
2106    &Open.McastBuffer,
2107    SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
2108    );
2109
2110  Status = PxeUndiOpen (SimpleNetworkDevice, &Open);
2111
2112  if (EFI_ERROR (Status)) {
2113    DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiOpen() - Status = %r\n", Status));
2114    return Status;
2115  }
2116  //
2117  // Check the status code from the 16 bit UNDI ROM
2118  //
2119  if (Open.Status != PXENV_STATUS_SUCCESS) {
2120    DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiOpen() - Open.Status = %04x\n", Open.Status));
2121    return EFI_DEVICE_ERROR;
2122  }
2123  //
2124  // The UNDI interface has been initialized, so update the State.
2125  //
2126  SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkInitialized;
2127
2128  //
2129  // If initialize succeeds, then assume that media is present.
2130  //
2131  SimpleNetworkDevice->SimpleNetworkMode.MediaPresent = TRUE;
2132
2133  //
2134  // Reset the recycled transmit buffer FIFO
2135  //
2136  SimpleNetworkDevice->TxBufferFifo.First = 0;
2137  SimpleNetworkDevice->TxBufferFifo.Last  = 0;
2138  SimpleNetworkDevice->IsrValid           = FALSE;
2139
2140  return Status;
2141}
2142//
2143// Reset()
2144//
2145/**
2146  Reset network interface.
2147
2148  @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
2149  @param ExtendedVerification Need extended verfication.
2150
2151  @retval EFI_INVALID_PARAMETER Invalid This parameter.
2152  @retval EFI_DEVICE_ERROR      Network device has not been initialized.
2153  @retval EFI_NOT_STARTED       Network device has been stopped.
2154  @retval EFI_DEVICE_ERROR      Invalid status for network device
2155  @retval EFI_SUCCESS           Success operation.
2156**/
2157EFI_STATUS
2158EFIAPI
2159Undi16SimpleNetworkReset (
2160  IN EFI_SIMPLE_NETWORK_PROTOCOL   *This,
2161  IN BOOLEAN                       ExtendedVerification
2162  )
2163{
2164  EFI_STATUS              Status;
2165  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
2166  PXENV_UNDI_RESET_T      Reset;
2167  UINT16                  Rx_filter;
2168
2169  if (This == NULL) {
2170    return EFI_INVALID_PARAMETER;
2171  }
2172
2173  Status              = EFI_SUCCESS;
2174  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
2175
2176  if (SimpleNetworkDevice == NULL) {
2177    return EFI_DEVICE_ERROR;
2178  }
2179  //
2180  // Verify that the current state of the adapter is valid for this call.
2181  //
2182  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
2183  case EfiSimpleNetworkStopped:
2184    return EFI_NOT_STARTED;
2185
2186  case EfiSimpleNetworkInitialized:
2187    break;
2188
2189  case EfiSimpleNetworkStarted:
2190  default:
2191    return EFI_DEVICE_ERROR;
2192  }
2193
2194  Reset.Status  = INIT_PXE_STATUS;
2195
2196  Rx_filter     = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);
2197
2198  Undi16GetMCastFilters (
2199    &SimpleNetworkDevice->SimpleNetworkMode,
2200    &Reset.R_Mcast_Buf,
2201    SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
2202    );
2203
2204  Status = PxeUndiResetNic (SimpleNetworkDevice, &Reset, Rx_filter);
2205
2206  if (EFI_ERROR (Status)) {
2207    return Status;
2208  }
2209  //
2210  // Check the status code from the 16 bit UNDI ROM
2211  //
2212  if (Reset.Status != PXENV_STATUS_SUCCESS) {
2213    return EFI_DEVICE_ERROR;
2214  }
2215  //
2216  // Reset the recycled transmit buffer FIFO
2217  //
2218  SimpleNetworkDevice->TxBufferFifo.First = 0;
2219  SimpleNetworkDevice->TxBufferFifo.Last  = 0;
2220  SimpleNetworkDevice->IsrValid           = FALSE;
2221
2222  return Status;
2223}
2224//
2225// Shutdown()
2226//
2227/**
2228  Shutdown network interface.
2229
2230  @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
2231
2232  @retval EFI_INVALID_PARAMETER Invalid This parameter.
2233  @retval EFI_DEVICE_ERROR      Network device has not been initialized.
2234  @retval EFI_NOT_STARTED       Network device has been stopped.
2235  @retval EFI_DEVICE_ERROR      Invalid status for network device
2236  @retval EFI_SUCCESS           Success operation.
2237**/
2238EFI_STATUS
2239EFIAPI
2240Undi16SimpleNetworkShutdown (
2241  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
2242  )
2243{
2244  EFI_STATUS              Status;
2245  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
2246  PXENV_UNDI_CLOSE_T      Close;
2247  PXENV_UNDI_SHUTDOWN_T   Shutdown;
2248
2249  if (This == NULL) {
2250    return EFI_INVALID_PARAMETER;
2251  }
2252
2253  Status              = EFI_SUCCESS;
2254  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
2255
2256  if (SimpleNetworkDevice == NULL) {
2257    return EFI_DEVICE_ERROR;
2258  }
2259  //
2260  // Verify that the current state of the adapter is valid for this call.
2261  //
2262  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
2263  case EfiSimpleNetworkStopped:
2264    return EFI_NOT_STARTED;
2265
2266  case EfiSimpleNetworkInitialized:
2267    break;
2268
2269  case EfiSimpleNetworkStarted:
2270  default:
2271    return EFI_DEVICE_ERROR;
2272  }
2273
2274  SimpleNetworkDevice->IsrValid = FALSE;
2275
2276  //
2277  // Call 16 bit UNDI ROM to start the network interface
2278  //
2279  Close.Status  = INIT_PXE_STATUS;
2280
2281  Status        = PxeUndiClose (SimpleNetworkDevice, &Close);
2282
2283  if (EFI_ERROR (Status)) {
2284    return Status;
2285  }
2286  //
2287  // Check the status code from the 16 bit UNDI ROM
2288  //
2289  if (Close.Status != PXENV_STATUS_SUCCESS) {
2290    return EFI_DEVICE_ERROR;
2291  }
2292  //
2293  // Call 16 bit UNDI ROM to open the network interface
2294  //
2295  Shutdown.Status = INIT_PXE_STATUS;
2296
2297  Status          = PxeUndiShutdown (SimpleNetworkDevice, &Shutdown);
2298
2299  if (EFI_ERROR (Status)) {
2300    return Status;
2301  }
2302  //
2303  // Check the status code from the 16 bit UNDI ROM
2304  //
2305  if (Shutdown.Status != PXENV_STATUS_SUCCESS) {
2306    return EFI_DEVICE_ERROR;
2307  }
2308  //
2309  // The UNDI interface has been initialized, so update the State.
2310  //
2311  SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStarted;
2312
2313  //
2314  // If shutdown succeeds, then assume that media is not present.
2315  //
2316  SimpleNetworkDevice->SimpleNetworkMode.MediaPresent = FALSE;
2317
2318  //
2319  // Reset the recycled transmit buffer FIFO
2320  //
2321  SimpleNetworkDevice->TxBufferFifo.First = 0;
2322  SimpleNetworkDevice->TxBufferFifo.Last  = 0;
2323
2324  //
2325  // A short delay.  Without this an initialize immediately following
2326  // a shutdown will cause some versions of UNDI-16 to stop operating.
2327  //
2328  gBS->Stall (250000);
2329
2330  return Status;
2331}
2332//
2333// ReceiveFilters()
2334//
2335/**
2336  Reset network interface.
2337
2338  @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
2339  @param Enable               Enable mask value
2340  @param Disable              Disable mask value
2341  @param ResetMCastFilter     Whether reset multi cast filter or not
2342  @param MCastFilterCnt       Count of mutli cast filter for different MAC address
2343  @param MCastFilter          Buffer for mustli cast filter for different MAC address.
2344
2345  @retval EFI_INVALID_PARAMETER Invalid This parameter.
2346  @retval EFI_DEVICE_ERROR      Network device has not been initialized.
2347  @retval EFI_NOT_STARTED       Network device has been stopped.
2348  @retval EFI_DEVICE_ERROR      Invalid status for network device
2349  @retval EFI_SUCCESS           Success operation.
2350**/
2351EFI_STATUS
2352EFIAPI
2353Undi16SimpleNetworkReceiveFilters (
2354  IN EFI_SIMPLE_NETWORK_PROTOCOL                     * This,
2355  IN UINT32                                          Enable,
2356  IN UINT32                                          Disable,
2357  IN BOOLEAN                                         ResetMCastFilter,
2358  IN UINTN                                           MCastFilterCnt     OPTIONAL,
2359  IN EFI_MAC_ADDRESS                                 * MCastFilter OPTIONAL
2360  )
2361{
2362  EFI_STATUS              Status;
2363  UINTN                   Index;
2364  UINT32                  NewFilter;
2365  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
2366  PXENV_UNDI_CLOSE_T      Close;
2367  PXENV_UNDI_OPEN_T       Open;
2368
2369  if (This == NULL) {
2370    return EFI_INVALID_PARAMETER;
2371  }
2372
2373  Status              = EFI_SUCCESS;
2374  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
2375
2376  if (SimpleNetworkDevice == NULL) {
2377    return EFI_DEVICE_ERROR;
2378  }
2379  //
2380  // Verify that the current state of the adapter is valid for this call.
2381  //
2382  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
2383  case EfiSimpleNetworkStopped:
2384    return EFI_NOT_STARTED;
2385
2386  case EfiSimpleNetworkInitialized:
2387    break;
2388
2389  case EfiSimpleNetworkStarted:
2390  default:
2391    return EFI_DEVICE_ERROR;
2392  }
2393  //
2394  // First deal with possible filter setting changes
2395  //
2396  if ((Enable == 0) && (Disable == 0) && !ResetMCastFilter) {
2397    return EFI_SUCCESS;
2398  }
2399
2400  NewFilter = (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting | Enable) &~Disable;
2401
2402  if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
2403    if ((MCastFilterCnt == 0) || (MCastFilter == 0) || MCastFilterCnt > SimpleNetworkDevice->SimpleNetworkMode.MaxMCastFilterCount) {
2404      return EFI_INVALID_PARAMETER;
2405    }
2406  }
2407  //
2408  // Call 16 bit UNDI ROM to close the network interface
2409  //
2410  Close.Status  = INIT_PXE_STATUS;
2411
2412  Status        = PxeUndiClose (SimpleNetworkDevice, &Close);
2413
2414  if (EFI_ERROR (Status)) {
2415    return Status;
2416  }
2417  //
2418  // Check the status code from the 16 bit UNDI ROM
2419  //
2420  if (Close.Status != PXENV_STATUS_SUCCESS) {
2421    return EFI_DEVICE_ERROR;
2422  }
2423  //
2424  // Call 16 bit UNDI ROM to open the network interface
2425  //
2426  //
2427  // Reset the recycled transmit buffer FIFO
2428  //
2429  SimpleNetworkDevice->TxBufferFifo.First = 0;
2430  SimpleNetworkDevice->TxBufferFifo.Last  = 0;
2431
2432  //
2433  // Call 16 bit UNDI ROM to open the network interface
2434  //
2435  ZeroMem (&Open, sizeof Open);
2436
2437  Open.Status     = INIT_PXE_STATUS;
2438  Open.PktFilter  = Undi16GetPacketFilterSetting (NewFilter);
2439
2440  if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
2441    //
2442    // Copy the MAC addresses into the UNDI open parameter structure
2443    //
2444    Open.McastBuffer.MCastAddrCount = (UINT16) MCastFilterCnt;
2445    for (Index = 0; Index < MCastFilterCnt; ++Index) {
2446      CopyMem (
2447        Open.McastBuffer.MCastAddr[Index],
2448        &MCastFilter[Index],
2449        sizeof Open.McastBuffer.MCastAddr[Index]
2450        );
2451    }
2452  } else if (!ResetMCastFilter) {
2453    for (Index = 0; Index < SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount; ++Index) {
2454      CopyMem (
2455        Open.McastBuffer.MCastAddr[Index],
2456        &SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index],
2457        sizeof Open.McastBuffer.MCastAddr[Index]
2458        );
2459    }
2460  }
2461
2462  Status = PxeUndiOpen (SimpleNetworkDevice, &Open);
2463
2464  if (EFI_ERROR (Status)) {
2465    return Status;
2466  }
2467  //
2468  // Check the status code from the 16 bit UNDI ROM
2469  //
2470  if (Open.Status != PXENV_STATUS_SUCCESS) {
2471    return EFI_DEVICE_ERROR;
2472  }
2473
2474  SimpleNetworkDevice->IsrValid = FALSE;
2475  SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting = NewFilter;
2476
2477  if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
2478    SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount = (UINT32) MCastFilterCnt;
2479    for (Index = 0; Index < MCastFilterCnt; ++Index) {
2480      CopyMem (
2481        &SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index],
2482        &MCastFilter[Index],
2483        sizeof (EFI_MAC_ADDRESS)
2484        );
2485    }
2486  }
2487  //
2488  // Read back multicast addresses.
2489  //
2490  return EFI_SUCCESS;
2491}
2492//
2493// StationAddress()
2494//
2495/**
2496  Set new MAC address.
2497
2498  @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
2499  @param Reset                Whether reset station MAC address to permanent address
2500  @param New                  A pointer to New address
2501
2502  @retval EFI_INVALID_PARAMETER Invalid This parameter.
2503  @retval EFI_DEVICE_ERROR      Network device has not been initialized.
2504  @retval EFI_NOT_STARTED       Network device has been stopped.
2505  @retval EFI_DEVICE_ERROR      Invalid status for network device
2506  @retval EFI_SUCCESS           Success operation.
2507**/
2508EFI_STATUS
2509EFIAPI
2510Undi16SimpleNetworkStationAddress (
2511  IN EFI_SIMPLE_NETWORK_PROTOCOL           * This,
2512  IN BOOLEAN                               Reset,
2513  IN EFI_MAC_ADDRESS                       * New OPTIONAL
2514  )
2515{
2516  EFI_STATUS                    Status;
2517  EFI_SIMPLE_NETWORK_DEV        *SimpleNetworkDevice;
2518  PXENV_UNDI_SET_STATION_ADDR_T SetStationAddr;
2519  //
2520  // EFI_DEVICE_PATH_PROTOCOL     *OldDevicePath;
2521  //
2522  PXENV_UNDI_CLOSE_T            Close;
2523  PXENV_UNDI_OPEN_T             Open;
2524
2525  if (This == NULL) {
2526    return EFI_INVALID_PARAMETER;
2527  }
2528
2529  Status              = EFI_SUCCESS;
2530
2531  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
2532
2533  if (SimpleNetworkDevice == NULL) {
2534    return EFI_DEVICE_ERROR;
2535  }
2536  //
2537  // Verify that the current state of the adapter is valid for this call.
2538  //
2539  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
2540  case EfiSimpleNetworkInitialized:
2541    break;
2542
2543  case EfiSimpleNetworkStopped:
2544    return EFI_NOT_STARTED;
2545
2546  case EfiSimpleNetworkStarted:
2547  default:
2548    return EFI_DEVICE_ERROR;
2549  }
2550  //
2551  // Call 16 bit UNDI ROM to open the network interface
2552  //
2553  SetStationAddr.Status = INIT_PXE_STATUS;
2554
2555  if (Reset) {
2556    //
2557    // If we are resetting the Station Address to the permanent address, and the
2558    // Station Address is not programmable, then just return EFI_SUCCESS.
2559    //
2560    if (!SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable) {
2561      return EFI_SUCCESS;
2562    }
2563    //
2564    // If the address is already the permanent address, then just return success.
2565    //
2566    if (CompareMem (
2567          &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
2568          &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
2569          SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
2570          ) == 0) {
2571      return EFI_SUCCESS;
2572    }
2573    //
2574    // Copy the adapters permanent address to the new station address
2575    //
2576    CopyMem (
2577      &SetStationAddr.StationAddress,
2578      &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
2579      SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
2580      );
2581  } else {
2582    //
2583    // If we are setting the Station Address, and the
2584    // Station Address is not programmable, return invalid parameter.
2585    //
2586    if (!SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable) {
2587      return EFI_INVALID_PARAMETER;
2588    }
2589    //
2590    // If the address is already the new address, then just return success.
2591    //
2592    if (CompareMem (
2593          &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
2594          New,
2595          SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
2596          ) == 0) {
2597      return EFI_SUCCESS;
2598    }
2599    //
2600    // Copy New to the new station address
2601    //
2602    CopyMem (
2603      &SetStationAddr.StationAddress,
2604      New,
2605      SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
2606      );
2607
2608  }
2609  //
2610  // Call 16 bit UNDI ROM to stop the network interface
2611  //
2612  Close.Status = INIT_PXE_STATUS;
2613
2614  PxeUndiClose (SimpleNetworkDevice, &Close);
2615
2616  //
2617  // Call 16-bit UNDI ROM to set the station address
2618  //
2619  SetStationAddr.Status = PXENV_STATUS_SUCCESS;
2620
2621  Status                = PxeUndiSetStationAddr (SimpleNetworkDevice, &SetStationAddr);
2622
2623  //
2624  // Call 16-bit UNDI ROM to start the network interface
2625  //
2626  Open.Status     = PXENV_STATUS_SUCCESS;
2627  Open.OpenFlag   = 0;
2628  Open.PktFilter  = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);
2629  Undi16GetMCastFilters (
2630    &SimpleNetworkDevice->SimpleNetworkMode,
2631    &Open.McastBuffer,
2632    SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
2633    );
2634
2635  PxeUndiOpen (SimpleNetworkDevice, &Open);
2636
2637  //
2638  // Check status from station address change
2639  //
2640  if (EFI_ERROR (Status)) {
2641    return Status;
2642  }
2643  //
2644  // Check the status code from the 16 bit UNDI ROM
2645  //
2646  if (SetStationAddr.Status != PXENV_STATUS_SUCCESS) {
2647    return EFI_DEVICE_ERROR;
2648  }
2649
2650  CopyMem (
2651    &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
2652    &SetStationAddr.StationAddress,
2653    SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
2654    );
2655
2656#if 0 /* The device path is based on the permanent address not the current address. */
2657  //
2658  // The station address was changed, so update the device path with the new MAC address.
2659  //
2660  OldDevicePath                   = SimpleNetworkDevice->DevicePath;
2661  SimpleNetworkDevice->DevicePath = DuplicateDevicePath (SimpleNetworkDevice->BaseDevicePath);
2662  SimpleNetworkAppendMacAddressDevicePath (
2663    &SimpleNetworkDevice->DevicePath,
2664    &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress
2665    );
2666
2667  Status = LibReinstallProtocolInterfaces (
2668            SimpleNetworkDevice->Handle,
2669            &DevicePathProtocol,
2670            OldDevicePath,
2671            SimpleNetworkDevice->DevicePath,
2672            NULL
2673            );
2674
2675  if (EFI_ERROR (Status)) {
2676    DEBUG ((DEBUG_ERROR, "Failed to reinstall the DevicePath protocol for the Simple Network Device\n"));
2677    DEBUG ((DEBUG_ERROR, "  Status = %r\n", Status));
2678  }
2679
2680  FreePool (OldDevicePath);
2681#endif /* 0 */
2682
2683  return Status;
2684}
2685//
2686// Statistics()
2687//
2688/**
2689  Resets or collects the statistics on a network interface.
2690
2691  @param  This            Protocol instance pointer.
2692  @param  Reset           Set to TRUE to reset the statistics for the network interface.
2693  @param  StatisticsSize  On input the size, in bytes, of StatisticsTable. On
2694                          output the size, in bytes, of the resulting table of
2695                          statistics.
2696  @param  StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that
2697                          contains the statistics.
2698
2699  @retval EFI_SUCCESS           The statistics were collected from the network interface.
2700  @retval EFI_NOT_STARTED       The network interface has not been started.
2701  @retval EFI_BUFFER_TOO_SMALL  The Statistics buffer was too small. The current buffer
2702                                size needed to hold the statistics is returned in
2703                                StatisticsSize.
2704  @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
2705  @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
2706  @retval EFI_UNSUPPORTED       This function is not supported by the network interface.
2707
2708**/
2709EFI_STATUS
2710EFIAPI
2711Undi16SimpleNetworkStatistics (
2712  IN EFI_SIMPLE_NETWORK_PROTOCOL       * This,
2713  IN BOOLEAN                           Reset,
2714  IN OUT UINTN                         *StatisticsSize OPTIONAL,
2715  OUT EFI_NETWORK_STATISTICS           * StatisticsTable OPTIONAL
2716  )
2717{
2718  EFI_STATUS                    Status;
2719  EFI_SIMPLE_NETWORK_DEV        *SimpleNetworkDevice;
2720  PXENV_UNDI_CLEAR_STATISTICS_T ClearStatistics;
2721  PXENV_UNDI_GET_STATISTICS_T   GetStatistics;
2722
2723  if (This == NULL) {
2724    return EFI_INVALID_PARAMETER;
2725  }
2726
2727  Status              = EFI_SUCCESS;
2728  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
2729
2730  if (SimpleNetworkDevice == NULL) {
2731    return EFI_DEVICE_ERROR;
2732  }
2733  //
2734  // Verify that the current state of the adapter is valid for this call.
2735  //
2736  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
2737  case EfiSimpleNetworkInitialized:
2738    break;
2739
2740  case EfiSimpleNetworkStopped:
2741    return EFI_NOT_STARTED;
2742
2743  case EfiSimpleNetworkStarted:
2744  default:
2745    return EFI_DEVICE_ERROR;
2746  }
2747
2748  if ((StatisticsSize != NULL) && (*StatisticsSize != 0) && (StatisticsTable == NULL)) {
2749    return EFI_INVALID_PARAMETER;
2750  }
2751
2752  //
2753  // If Reset is TRUE, then clear all the statistics.
2754  //
2755  if (Reset) {
2756
2757    DEBUG ((DEBUG_NET, "  RESET Statistics\n"));
2758
2759    //
2760    // Call 16 bit UNDI ROM to open the network interface
2761    //
2762    ClearStatistics.Status  = INIT_PXE_STATUS;
2763
2764    Status                  = PxeUndiClearStatistics (SimpleNetworkDevice, &ClearStatistics);
2765
2766    if (EFI_ERROR (Status)) {
2767      return Status;
2768    }
2769    //
2770    // Check the status code from the 16 bit UNDI ROM
2771    //
2772    if (ClearStatistics.Status != PXENV_STATUS_SUCCESS) {
2773      return EFI_DEVICE_ERROR;
2774    }
2775
2776    DEBUG ((DEBUG_NET, "  RESET Statistics Complete"));
2777  }
2778
2779  if (StatisticsSize != NULL) {
2780    EFI_NETWORK_STATISTICS  LocalStatisticsTable;
2781
2782    DEBUG ((DEBUG_NET, "  GET Statistics\n"));
2783
2784    //
2785    // If the size if valid, then see if the table is valid
2786    //
2787    if (StatisticsTable == NULL) {
2788      DEBUG ((DEBUG_NET, "  StatisticsTable is NULL\n"));
2789      return EFI_INVALID_PARAMETER;
2790    }
2791    //
2792    // Call 16 bit UNDI ROM to open the network interface
2793    //
2794    GetStatistics.Status            = INIT_PXE_STATUS;
2795    GetStatistics.XmtGoodFrames     = 0;
2796    GetStatistics.RcvGoodFrames     = 0;
2797    GetStatistics.RcvCRCErrors      = 0;
2798    GetStatistics.RcvResourceErrors = 0;
2799
2800    Status                          = PxeUndiGetStatistics (SimpleNetworkDevice, &GetStatistics);
2801
2802    if (EFI_ERROR (Status)) {
2803      return Status;
2804    }
2805    //
2806    // Check the status code from the 16 bit UNDI ROM
2807    //
2808    if (GetStatistics.Status != PXENV_STATUS_SUCCESS) {
2809      return EFI_DEVICE_ERROR;
2810    }
2811    //
2812    // Fill in the Statistics Table with the collected values.
2813    //
2814    SetMem (&LocalStatisticsTable, sizeof LocalStatisticsTable, 0xff);
2815
2816    LocalStatisticsTable.TxGoodFrames     = GetStatistics.XmtGoodFrames;
2817    LocalStatisticsTable.RxGoodFrames     = GetStatistics.RcvGoodFrames;
2818    LocalStatisticsTable.RxCrcErrorFrames = GetStatistics.RcvCRCErrors;
2819    LocalStatisticsTable.RxDroppedFrames  = GetStatistics.RcvResourceErrors;
2820
2821    CopyMem (StatisticsTable, &LocalStatisticsTable, *StatisticsSize);
2822
2823    DEBUG (
2824      (DEBUG_NET,
2825      "  Statistics Collected : Size=%d  Buf=%08x\n",
2826      *StatisticsSize,
2827      StatisticsTable)
2828      );
2829
2830    DEBUG ((DEBUG_NET, "  GET Statistics Complete"));
2831
2832    if (*StatisticsSize < sizeof LocalStatisticsTable) {
2833      DEBUG ((DEBUG_NET, "  BUFFER TOO SMALL\n"));
2834      Status = EFI_BUFFER_TOO_SMALL;
2835    }
2836
2837    *StatisticsSize = sizeof LocalStatisticsTable;
2838
2839    return Status;
2840
2841  }
2842
2843  return EFI_SUCCESS;
2844}
2845//
2846// MCastIpToMac()
2847//
2848/**
2849  Translate IP address to MAC address.
2850
2851  @param This                 A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
2852  @param IPv6                 IPv6 or IPv4
2853  @param IP                   A pointer to given Ip address.
2854  @param MAC                  On return, translated MAC address.
2855
2856  @retval EFI_INVALID_PARAMETER Invalid This parameter.
2857  @retval EFI_INVALID_PARAMETER Invalid IP address.
2858  @retval EFI_INVALID_PARAMETER Invalid return buffer for holding MAC address.
2859  @retval EFI_UNSUPPORTED       Do not support IPv6
2860  @retval EFI_DEVICE_ERROR      Network device has not been initialized.
2861  @retval EFI_NOT_STARTED       Network device has been stopped.
2862  @retval EFI_DEVICE_ERROR      Invalid status for network device
2863  @retval EFI_SUCCESS           Success operation.
2864**/
2865EFI_STATUS
2866EFIAPI
2867Undi16SimpleNetworkMCastIpToMac (
2868  IN EFI_SIMPLE_NETWORK_PROTOCOL            *This,
2869  IN BOOLEAN                                IPv6,
2870  IN EFI_IP_ADDRESS                         *IP,
2871  OUT EFI_MAC_ADDRESS                       *MAC
2872  )
2873{
2874  EFI_STATUS                  Status;
2875  EFI_SIMPLE_NETWORK_DEV      *SimpleNetworkDevice;
2876  PXENV_UNDI_GET_MCAST_ADDR_T GetMcastAddr;
2877
2878  if (This == NULL || IP == NULL || MAC == NULL) {
2879    return EFI_INVALID_PARAMETER;
2880  }
2881
2882  Status              = EFI_SUCCESS;
2883  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
2884
2885  if (SimpleNetworkDevice == NULL) {
2886    return EFI_DEVICE_ERROR;
2887  }
2888  //
2889  // Verify that the current state of the adapter is valid for this call.
2890  //
2891  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
2892  case EfiSimpleNetworkStopped:
2893    return EFI_NOT_STARTED;
2894
2895  case EfiSimpleNetworkInitialized:
2896    break;
2897
2898  case EfiSimpleNetworkStarted:
2899  default:
2900    return EFI_DEVICE_ERROR;
2901  }
2902  //
2903  // 16 bit UNDI Option ROMS do not support IPv6.  Check for IPv6 usage.
2904  //
2905  if (IPv6) {
2906    return EFI_UNSUPPORTED;
2907  }
2908  //
2909  // Call 16 bit UNDI ROM to open the network interface
2910  //
2911  GetMcastAddr.Status = INIT_PXE_STATUS;
2912  CopyMem (&GetMcastAddr.InetAddr, IP, 4);
2913
2914  Status = PxeUndiGetMcastAddr (SimpleNetworkDevice, &GetMcastAddr);
2915
2916  if (EFI_ERROR (Status)) {
2917    return Status;
2918  }
2919  //
2920  // Check the status code from the 16 bit UNDI ROM
2921  //
2922  if (GetMcastAddr.Status != PXENV_STATUS_SUCCESS) {
2923    return EFI_DEVICE_ERROR;
2924  }
2925  //
2926  // Copy the MAC address from the returned data structure.
2927  //
2928  CopyMem (
2929    MAC,
2930    &GetMcastAddr.MediaAddr,
2931    SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
2932    );
2933
2934  return Status;
2935}
2936//
2937// NvData()
2938//
2939/**
2940  Performs read and write operations on the NVRAM device attached to a
2941  network interface.
2942
2943  @param  This       The protocol instance pointer.
2944  @param  ReadWrite  TRUE for read operations, FALSE for write operations.
2945  @param  Offset     Byte offset in the NVRAM device at which to start the read or
2946                     write operation. This must be a multiple of NvRamAccessSize and
2947                     less than NvRamSize.
2948  @param  BufferSize The number of bytes to read or write from the NVRAM device.
2949                     This must also be a multiple of NvramAccessSize.
2950  @param  Buffer     A pointer to the data buffer.
2951
2952  @retval EFI_SUCCESS           The NVRAM access was performed.
2953  @retval EFI_NOT_STARTED       The network interface has not been started.
2954  @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
2955  @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
2956  @retval EFI_UNSUPPORTED       This function is not supported by the network interface.
2957
2958**/
2959EFI_STATUS
2960EFIAPI
2961Undi16SimpleNetworkNvData (
2962  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This,
2963  IN BOOLEAN                      ReadWrite,
2964  IN UINTN                        Offset,
2965  IN UINTN                        BufferSize,
2966  IN OUT VOID                     *Buffer
2967  )
2968{
2969  return EFI_UNSUPPORTED;
2970}
2971//
2972// GetStatus()
2973//
2974/**
2975  Reads the current interrupt status and recycled transmit buffer status from
2976  a network interface.
2977
2978  @param  This            The protocol instance pointer.
2979  @param  InterruptStatus A pointer to the bit mask of the currently active interrupts
2980                          If this is NULL, the interrupt status will not be read from
2981                          the device. If this is not NULL, the interrupt status will
2982                          be read from the device. When the  interrupt status is read,
2983                          it will also be cleared. Clearing the transmit  interrupt
2984                          does not empty the recycled transmit buffer array.
2985  @param  TxBuf           Recycled transmit buffer address. The network interface will
2986                          not transmit if its internal recycled transmit buffer array
2987                          is full. Reading the transmit buffer does not clear the
2988                          transmit interrupt. If this is NULL, then the transmit buffer
2989                          status will not be read. If there are no transmit buffers to
2990                          recycle and TxBuf is not NULL, * TxBuf will be set to NULL.
2991
2992  @retval EFI_SUCCESS           The status of the network interface was retrieved.
2993  @retval EFI_NOT_STARTED       The network interface has not been started.
2994  @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
2995  @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
2996  @retval EFI_UNSUPPORTED       This function is not supported by the network interface.
2997
2998**/
2999EFI_STATUS
3000EFIAPI
3001Undi16SimpleNetworkGetStatus (
3002  IN EFI_SIMPLE_NETWORK_PROTOCOL  * This,
3003  OUT UINT32                      *InterruptStatus OPTIONAL,
3004  OUT VOID                        **TxBuf OPTIONAL
3005  )
3006{
3007  EFI_STATUS              Status;
3008  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
3009  UINTN                   FrameLength;
3010
3011  if (This == NULL) {
3012    return EFI_INVALID_PARAMETER;
3013  }
3014
3015  Status              = EFI_SUCCESS;
3016  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
3017
3018  if (SimpleNetworkDevice == NULL) {
3019    return EFI_DEVICE_ERROR;
3020  }
3021  //
3022  // Verify that the current state of the adapter is valid for this call.
3023  //
3024  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
3025  case EfiSimpleNetworkInitialized:
3026    break;
3027
3028  case EfiSimpleNetworkStopped:
3029    return EFI_NOT_STARTED;
3030
3031  case EfiSimpleNetworkStarted:
3032  default:
3033    return EFI_DEVICE_ERROR;
3034  }
3035
3036  if (InterruptStatus == NULL && TxBuf == NULL) {
3037    return EFI_INVALID_PARAMETER;
3038  }
3039
3040  FrameLength = 0;
3041  Status      = Undi16SimpleNetworkIsr (This, &FrameLength, NULL, NULL, NULL, NULL);
3042
3043  if (Status != EFI_BUFFER_TOO_SMALL) {
3044    if (EFI_ERROR (Status)) {
3045      return Status;
3046    }
3047  }
3048  //
3049  // See if the caller wants interrupt info.
3050  //
3051  if (InterruptStatus != NULL) {
3052    *InterruptStatus                      = SimpleNetworkDevice->InterruptStatus;
3053    SimpleNetworkDevice->InterruptStatus  = 0;
3054  }
3055  //
3056  // See if the caller wants transmit buffer status info.
3057  //
3058  if (TxBuf != NULL) {
3059    *TxBuf = 0;
3060    SimpleNetworkTransmitFifoRemove (&(SimpleNetworkDevice->TxBufferFifo), TxBuf);
3061  }
3062
3063  return EFI_SUCCESS;
3064}
3065
3066/**
3067  Places a packet in the transmit queue of a network interface.
3068
3069  @param  This       The protocol instance pointer.
3070  @param  HeaderSize The size, in bytes, of the media header to be filled in by
3071                     the Transmit() function. If HeaderSize is non-zero, then it
3072                     must be equal to This->Mode->MediaHeaderSize and the DestAddr
3073                     and Protocol parameters must not be NULL.
3074  @param  BufferSize The size, in bytes, of the entire packet (media header and
3075                     data) to be transmitted through the network interface.
3076  @param  Buffer     A pointer to the packet (media header followed by data) to be
3077                     transmitted. This parameter cannot be NULL. If HeaderSize is zero,
3078                     then the media header in Buffer must already be filled in by the
3079                     caller. If HeaderSize is non-zero, then the media header will be
3080                     filled in by the Transmit() function.
3081  @param  SrcAddr    The source HW MAC address. If HeaderSize is zero, then this parameter
3082                     is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then
3083                     This->Mode->CurrentAddress is used for the source HW MAC address.
3084  @param  DestAddr   The destination HW MAC address. If HeaderSize is zero, then this
3085                     parameter is ignored.
3086  @param  Protocol   The type of header to build. If HeaderSize is zero, then this
3087                     parameter is ignored. See RFC 1700, section "Ether Types", for
3088                     examples.
3089
3090  @retval EFI_SUCCESS           The packet was placed on the transmit queue.
3091  @retval EFI_NOT_STARTED       The network interface has not been started.
3092  @retval EFI_NOT_READY         The network interface is too busy to accept this transmit request.
3093  @retval EFI_BUFFER_TOO_SMALL  The BufferSize parameter is too small.
3094  @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
3095  @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
3096  @retval EFI_UNSUPPORTED       This function is not supported by the network interface.
3097
3098**/
3099EFI_STATUS
3100EFIAPI
3101Undi16SimpleNetworkTransmit (
3102  IN EFI_SIMPLE_NETWORK_PROTOCOL           *This,
3103  IN UINTN                                 HeaderSize,
3104  IN UINTN                                 BufferSize,
3105  IN VOID                                  *Buffer,
3106  IN EFI_MAC_ADDRESS                       *SrcAddr OPTIONAL,
3107  IN EFI_MAC_ADDRESS                       *DestAddr OPTIONAL,
3108  IN UINT16                                *Protocol OPTIONAL
3109  )
3110{
3111  EFI_STATUS              Status;
3112  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
3113  PXENV_UNDI_TRANSMIT_T   XmitInfo;
3114
3115  if (This == NULL) {
3116    return EFI_INVALID_PARAMETER;
3117  }
3118
3119  Status              = EFI_SUCCESS;
3120  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
3121
3122  if (SimpleNetworkDevice == NULL) {
3123    return EFI_DEVICE_ERROR;
3124  }
3125  //
3126  // Verify that the current state of the adapter is valid for this call.
3127  //
3128  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
3129  case EfiSimpleNetworkInitialized:
3130    break;
3131
3132  case EfiSimpleNetworkStopped:
3133    return EFI_NOT_STARTED;
3134
3135  case EfiSimpleNetworkStarted:
3136  default:
3137    return EFI_DEVICE_ERROR;
3138  }
3139
3140  if (Buffer == NULL) {
3141    return EFI_INVALID_PARAMETER;
3142  }
3143
3144  if (BufferSize < SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize) {
3145    return EFI_BUFFER_TOO_SMALL;
3146  }
3147
3148  if (HeaderSize != 0) {
3149    if (HeaderSize != SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize) {
3150      return EFI_INVALID_PARAMETER;
3151    }
3152
3153    if (DestAddr == NULL || Protocol == NULL) {
3154      return EFI_INVALID_PARAMETER;
3155    }
3156
3157    if (DestAddr != NULL) {
3158      CopyMem (
3159        Buffer,
3160        DestAddr,
3161        SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
3162        );
3163    }
3164
3165    if (SrcAddr == NULL) {
3166      SrcAddr = &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress;
3167    }
3168
3169    CopyMem (
3170      (UINT8 *) Buffer + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize,
3171      SrcAddr,
3172      SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
3173      );
3174
3175    if (Protocol != NULL) {
3176      *(UINT16 *) ((UINT8 *) Buffer + 2 * SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize) = (UINT16) (((*Protocol & 0xFF) << 8) | ((*Protocol >> 8) & 0xFF));
3177    }
3178  }
3179  //
3180  // See if the recycled transmit buffer FIFO is full.
3181  // If it is full, then we can not transmit until the caller calls GetStatus() to pull
3182  // off recycled transmit buffers.
3183  //
3184  if (SimpleNetworkTransmitFifoFull (&(SimpleNetworkDevice->TxBufferFifo))) {
3185    return EFI_NOT_READY;
3186  }
3187  //
3188  //  Output debug trace message.
3189  //
3190  DEBUG ((DEBUG_NET, "Undi16SimpleNetworkTransmit\n\r "));
3191
3192  //
3193  // Initialize UNDI WRITE parameter structure.
3194  //
3195  XmitInfo.Status           = INIT_PXE_STATUS;
3196  XmitInfo.Protocol         = P_UNKNOWN;
3197  XmitInfo.XmitFlag         = XMT_DESTADDR;
3198  XmitInfo.DestAddrOffset   = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->TxDestAddr & 0x000f);
3199  XmitInfo.DestAddrSegment  = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->TxDestAddr >> 4);
3200  XmitInfo.TBDOffset        = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->Xmit & 0x000f);
3201  XmitInfo.TBDSegment       = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->Xmit >> 4);
3202  XmitInfo.Reserved[0]      = 0;
3203  XmitInfo.Reserved[1]      = 0;
3204
3205  CopyMem (
3206    SimpleNetworkDevice->TxDestAddr,
3207    Buffer,
3208    SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
3209    );
3210
3211  CopyMem (
3212    SimpleNetworkDevice->TxRealModeMediaHeader,
3213    Buffer,
3214    SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize
3215    );
3216
3217  SimpleNetworkDevice->Xmit->ImmedLength            = (UINT16) SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize;
3218
3219  SimpleNetworkDevice->Xmit->DataBlock[0].TDDataLen = (UINT16) (BufferSize - SimpleNetworkDevice->Xmit->ImmedLength);
3220
3221  CopyMem (
3222    SimpleNetworkDevice->TxRealModeDataBuffer,
3223    (UINT8 *) Buffer + SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize,
3224    SimpleNetworkDevice->Xmit->DataBlock[0].TDDataLen
3225    );
3226
3227  //
3228  // Make API call to UNDI TRANSMIT
3229  //
3230  XmitInfo.Status = 0;
3231
3232  Status          = PxeUndiTransmit (SimpleNetworkDevice, &XmitInfo);
3233
3234  if (EFI_ERROR (Status)) {
3235    return Status;
3236  }
3237  //
3238  // Check the status code from the 16 bit UNDI ROM
3239  //
3240  switch (XmitInfo.Status) {
3241  case PXENV_STATUS_OUT_OF_RESOURCES:
3242    return EFI_NOT_READY;
3243
3244  case PXENV_STATUS_SUCCESS:
3245    break;
3246
3247  default:
3248    return EFI_DEVICE_ERROR;
3249  }
3250  //
3251  // Add address of Buffer to the recycled transmit buffer FIFO
3252  //
3253  SimpleNetworkTransmitFifoAdd (&(SimpleNetworkDevice->TxBufferFifo), Buffer);
3254
3255  return EFI_SUCCESS;
3256}
3257
3258/**
3259  Receives a packet from a network interface.
3260
3261  @param  This       The protocol instance pointer.
3262  @param  HeaderSize The size, in bytes, of the media header received on the network
3263                     interface. If this parameter is NULL, then the media header size
3264                     will not be returned.
3265  @param  BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in
3266                     bytes, of the packet that was received on the network interface.
3267  @param  Buffer     A pointer to the data buffer to receive both the media header and
3268                     the data.
3269  @param  SrcAddr    The source HW MAC address. If this parameter is NULL, the
3270                     HW MAC source address will not be extracted from the media
3271                     header.
3272  @param  DestAddr   The destination HW MAC address. If this parameter is NULL,
3273                     the HW MAC destination address will not be extracted from the
3274                     media header.
3275  @param  Protocol   The media header type. If this parameter is NULL, then the
3276                     protocol will not be extracted from the media header. See
3277                     RFC 1700 section "Ether Types" for examples.
3278
3279  @retval  EFI_SUCCESS           The received data was stored in Buffer, and BufferSize has
3280                                 been updated to the number of bytes received.
3281  @retval  EFI_NOT_STARTED       The network interface has not been started.
3282  @retval  EFI_NOT_READY         The network interface is too busy to accept this transmit
3283                                 request.
3284  @retval  EFI_BUFFER_TOO_SMALL  The BufferSize parameter is too small.
3285  @retval  EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
3286  @retval  EFI_DEVICE_ERROR      The command could not be sent to the network interface.
3287  @retval  EFI_UNSUPPORTED       This function is not supported by the network interface.
3288
3289**/
3290EFI_STATUS
3291EFIAPI
3292Undi16SimpleNetworkReceive (
3293  IN EFI_SIMPLE_NETWORK_PROTOCOL            *This,
3294  OUT UINTN                                 *HeaderSize OPTIONAL,
3295  IN OUT UINTN                              *BufferSize,
3296  OUT VOID                                  *Buffer,
3297  OUT EFI_MAC_ADDRESS                       *SrcAddr OPTIONAL,
3298  OUT EFI_MAC_ADDRESS                       *DestAddr OPTIONAL,
3299  OUT UINT16                                *Protocol OPTIONAL
3300  )
3301{
3302  EFI_STATUS              Status;
3303  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
3304  UINTN                   MediaAddrSize;
3305  UINT8                   ProtType;
3306
3307  if (This == NULL || BufferSize == NULL || Buffer == NULL) {
3308    return EFI_INVALID_PARAMETER;
3309  }
3310
3311  Status              = EFI_SUCCESS;
3312  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
3313
3314  if (SimpleNetworkDevice == NULL) {
3315    return EFI_DEVICE_ERROR;
3316  }
3317  //
3318  // Verify that the current state of the adapter is valid for this call.
3319  //
3320  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
3321  case EfiSimpleNetworkInitialized:
3322    break;
3323
3324  case EfiSimpleNetworkStopped:
3325    return EFI_NOT_STARTED;
3326
3327  case EfiSimpleNetworkStarted:
3328  default:
3329    return EFI_DEVICE_ERROR;
3330  }
3331
3332  Status = Undi16SimpleNetworkIsr (
3333            This,
3334            BufferSize,
3335            HeaderSize,
3336            Buffer,
3337            &ProtType,
3338            NULL
3339            );
3340
3341  if (EFI_ERROR (Status)) {
3342    return Status;
3343  }
3344
3345  if ((SimpleNetworkDevice->InterruptStatus & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT) == 0) {
3346    return EFI_NOT_READY;
3347
3348  }
3349
3350  SimpleNetworkDevice->InterruptStatus &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
3351
3352  MediaAddrSize = This->Mode->HwAddressSize;
3353
3354  if (SrcAddr != NULL) {
3355    CopyMem (SrcAddr, (UINT8 *) Buffer + MediaAddrSize, MediaAddrSize);
3356  }
3357
3358  if (DestAddr != NULL) {
3359    CopyMem (DestAddr, Buffer, MediaAddrSize);
3360  }
3361
3362  if (Protocol != NULL) {
3363    *((UINT8 *) Protocol)     = *((UINT8 *) Buffer + (2 * MediaAddrSize) + 1);
3364    *((UINT8 *) Protocol + 1) = *((UINT8 *) Buffer + (2 * MediaAddrSize));
3365  }
3366
3367  DEBUG ((DEBUG_NET, "Packet Received: BufferSize=%d  HeaderSize = %d\n", *BufferSize, *HeaderSize));
3368
3369  return Status;
3370
3371}
3372//
3373// WaitForPacket()
3374//
3375/**
3376  wait for a packet to be received.
3377
3378  @param Event      Event used with WaitForEvent() to wait for a packet to be received.
3379  @param Context    Event Context
3380
3381**/
3382VOID
3383EFIAPI
3384Undi16SimpleNetworkWaitForPacket (
3385  IN EFI_EVENT               Event,
3386  IN VOID                    *Context
3387  )
3388{
3389  //
3390  // Someone is waiting on the receive packet event, if there's
3391  // a packet pending, signal the event
3392  //
3393  if (!EFI_ERROR (Undi16SimpleNetworkCheckForPacket (Context))) {
3394    gBS->SignalEvent (Event);
3395  }
3396}
3397//
3398// CheckForPacket()
3399//
3400/**
3401  Check whether packet is ready for receive.
3402
3403  @param This The protocol instance pointer.
3404
3405  @retval  EFI_SUCCESS           Receive data is ready.
3406  @retval  EFI_NOT_STARTED       The network interface has not been started.
3407  @retval  EFI_NOT_READY         The network interface is too busy to accept this transmit
3408                                 request.
3409  @retval  EFI_BUFFER_TOO_SMALL  The BufferSize parameter is too small.
3410  @retval  EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
3411  @retval  EFI_DEVICE_ERROR      The command could not be sent to the network interface.
3412  @retval  EFI_UNSUPPORTED       This function is not supported by the network interface.
3413**/
3414EFI_STATUS
3415Undi16SimpleNetworkCheckForPacket (
3416  IN EFI_SIMPLE_NETWORK_PROTOCOL *This
3417  )
3418{
3419  EFI_STATUS              Status;
3420  EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
3421  UINTN                   FrameLength;
3422
3423  if (This == NULL) {
3424    return EFI_INVALID_PARAMETER;
3425  }
3426
3427  Status              = EFI_SUCCESS;
3428  SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
3429
3430  if (SimpleNetworkDevice == NULL) {
3431    return EFI_DEVICE_ERROR;
3432  }
3433  //
3434  // Verify that the current state of the adapter is valid for this call.
3435  //
3436  switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
3437  case EfiSimpleNetworkInitialized:
3438    break;
3439
3440  case EfiSimpleNetworkStopped:
3441    return EFI_NOT_STARTED;
3442
3443  case EfiSimpleNetworkStarted:
3444  default:
3445    return EFI_DEVICE_ERROR;
3446  }
3447
3448  FrameLength = 0;
3449  Status = Undi16SimpleNetworkIsr (
3450            This,
3451            &FrameLength,
3452            NULL,
3453            NULL,
3454            NULL,
3455            NULL
3456            );
3457
3458  if (Status != EFI_BUFFER_TOO_SMALL) {
3459    if (EFI_ERROR (Status)) {
3460      return Status;
3461    }
3462  }
3463
3464  return ((SimpleNetworkDevice->InterruptStatus & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT) != 0) ? EFI_SUCCESS : EFI_NOT_READY;
3465}
3466
3467/**
3468  Signal handlers for ExitBootServices event.
3469
3470  Clean up any Real-mode UNDI residue from the system
3471
3472  @param Event      ExitBootServices event
3473  @param Context
3474**/
3475VOID
3476EFIAPI
3477Undi16SimpleNetworkEvent (
3478  IN EFI_EVENT        Event,
3479  IN VOID             *Context
3480  )
3481{
3482  //
3483  // NOTE:  This is not the only way to effect this cleanup.  The prescribed mechanism
3484  //        would be to perform an UNDI STOP command.  This strategam has been attempted
3485  //        but results in problems making some of the EFI core services from TPL_CALLBACK.
3486  //        This issue needs to be resolved, but the other alternative has been to perform
3487  //        the unchain logic explicitly, as done below.
3488  //
3489  RestoreCachedVectorAddress (0x1A);
3490}
3491
3492/**
3493  Allocate buffer below 1M for real mode.
3494
3495  @param NumPages     The number pages want to be allocated.
3496  @param Buffer       On return, allocated buffer.
3497
3498  @return Status of allocating pages.
3499**/
3500EFI_STATUS
3501BiosSnp16AllocatePagesBelowOneMb (
3502  UINTN  NumPages,
3503  VOID   **Buffer
3504  )
3505{
3506  EFI_STATUS            Status;
3507  EFI_PHYSICAL_ADDRESS  PhysicalAddress;
3508
3509  PhysicalAddress = 0x000fffff;
3510  Status = gBS->AllocatePages (
3511                  AllocateMaxAddress,
3512                  EfiRuntimeServicesData,
3513                  NumPages,
3514                  &PhysicalAddress
3515                  );
3516  if (EFI_ERROR (Status)) {
3517    return Status;
3518  }
3519
3520  *Buffer = (VOID *) (UINTN) PhysicalAddress;
3521  return EFI_SUCCESS;
3522}
3523