EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.c

Go to the documentation of this file.
00001 
00016 #include "BiosSnp16.h"
00017 
00018 
00022 EFI_DRIVER_BINDING_PROTOCOL gBiosSnp16DriverBinding = {
00023   BiosSnp16DriverBindingSupported,
00024   BiosSnp16DriverBindingStart,
00025   BiosSnp16DriverBindingStop,
00026   0x3,
00027   NULL,
00028   NULL
00029 };
00030 
00034 BOOLEAN     mCachedInt1A = FALSE;
00035 
00036 //
00037 // Private worker functions;
00038 //
00039 
00049 EFI_STATUS
00050 Undi16SimpleNetworkStartUndi (
00051   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice,
00052   UINT16                  Ax
00053   );
00054 
00063 EFI_STATUS
00064 Undi16SimpleNetworkStopUndi (
00065   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
00066   );
00067 
00076 EFI_STATUS
00077 Undi16SimpleNetworkCleanupUndi (
00078   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
00079   );
00080 
00089 EFI_STATUS
00090 Undi16SimpleNetworkGetInformation (
00091   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
00092   );
00093 
00102 EFI_STATUS
00103 Undi16SimpleNetworkGetNicType (
00104   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
00105   );
00106 
00115 EFI_STATUS
00116 Undi16SimpleNetworkGetNdisInfo (
00117   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
00118   );
00119 
00128 VOID
00129 EFIAPI
00130 Undi16SimpleNetworkEvent (
00131   IN EFI_EVENT  Event,
00132   IN VOID       *Context
00133   );
00134 
00143 EFI_STATUS
00144 Undi16SimpleNetworkLoadUndi (
00145   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
00146   );
00147 
00155 EFI_STATUS
00156 Undi16SimpleNetworkUnloadUndi (
00157   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
00158   );
00159 
00168 EFI_STATUS
00169 EFIAPI
00170 BiosSnp16DriverEntryPoint (
00171   IN EFI_HANDLE         ImageHandle,
00172   IN EFI_SYSTEM_TABLE   *SystemTable
00173   )
00174 {
00175   return EfiLibInstallDriverBindingComponentName2 (
00176            ImageHandle,
00177            SystemTable,
00178            &gBiosSnp16DriverBinding,
00179            ImageHandle,
00180            &gBiosSnp16ComponentName,
00181            &gBiosSnp16ComponentName2
00182            );
00183 }
00184 
00185 //
00186 // EFI Driver Binding Protocol Functions
00187 //
00200 EFI_STATUS
00201 EFIAPI
00202 BiosSnp16DriverBindingSupported (
00203   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
00204   IN EFI_HANDLE                   Controller,
00205   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
00206   )
00207 {
00208   EFI_STATUS                Status;
00209   EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
00210   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
00211   EFI_PCI_IO_PROTOCOL       *PciIo;
00212   PCI_TYPE00                Pci;
00213 
00214   //
00215   // See if the Legacy BIOS Protocol is available
00216   //
00217   Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
00218   if (EFI_ERROR (Status)) {
00219     return Status;
00220   }
00221   //
00222   // Open the IO Abstraction(s) needed to perform the supported test
00223   //
00224   Status = gBS->OpenProtocol (
00225                   Controller,
00226                   &gEfiDevicePathProtocolGuid,
00227                   (VOID **) &DevicePath,
00228                   This->DriverBindingHandle,
00229                   Controller,
00230                   EFI_OPEN_PROTOCOL_BY_DRIVER
00231                   );
00232   if (EFI_ERROR (Status)) {
00233     return Status;
00234   }
00235 
00236   gBS->CloseProtocol (
00237         Controller,
00238         &gEfiDevicePathProtocolGuid,
00239         This->DriverBindingHandle,
00240         Controller
00241         );
00242 
00243   //
00244   // Open the IO Abstraction(s) needed to perform the supported test
00245   //
00246   Status = gBS->OpenProtocol (
00247                   Controller,
00248                   &gEfiPciIoProtocolGuid,
00249                   (VOID **) &PciIo,
00250                   This->DriverBindingHandle,
00251                   Controller,
00252                   EFI_OPEN_PROTOCOL_BY_DRIVER
00253                   );
00254   if (EFI_ERROR (Status)) {
00255     return Status;
00256   }
00257   //
00258   // See if this is a PCI Network Controller by looking at the Command register and
00259   // Class Code Register
00260   //
00261   Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof (Pci) / sizeof (UINT32), &Pci);
00262   if (EFI_ERROR (Status)) {
00263     Status = EFI_UNSUPPORTED;
00264     goto Done;
00265   }
00266 
00267   Status = EFI_UNSUPPORTED;
00268   if (Pci.Hdr.ClassCode[2] == PCI_CLASS_NETWORK) {
00269     Status = EFI_SUCCESS;
00270   }
00271 
00272 Done:
00273   gBS->CloseProtocol (
00274         Controller,
00275         &gEfiPciIoProtocolGuid,
00276         This->DriverBindingHandle,
00277         Controller
00278         );
00279 
00280   return Status;
00281 }
00282 
00294 EFI_STATUS
00295 EFIAPI
00296 BiosSnp16DriverBindingStart (
00297   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
00298   IN EFI_HANDLE                   Controller,
00299   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
00300   )
00301 {
00302   EFI_STATUS                Status;
00303   EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
00304   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
00305   EFI_PCI_IO_PROTOCOL       *PciIo;
00306   EFI_SIMPLE_NETWORK_DEV    *SimpleNetworkDevice;
00307   EFI_DEV_PATH              Node;
00308   UINTN                     Index;
00309   UINTN                     Index2;
00310   UINTN                     Segment;
00311   UINTN                     Bus;
00312   UINTN                     Device;
00313   UINTN                     Function;
00314   UINTN                     Flags;
00315   UINT64                    Supports;
00316 
00317   SimpleNetworkDevice = NULL;
00318   PciIo               = NULL;
00319 
00320   //
00321   // See if the Legacy BIOS Protocol is available
00322   //
00323   Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
00324   if (EFI_ERROR (Status)) {
00325     return Status;
00326   }
00327   //
00328   // Open the IO Abstraction(s) needed
00329   //
00330   Status = gBS->OpenProtocol (
00331                   Controller,
00332                   &gEfiDevicePathProtocolGuid,
00333                   (VOID **) &DevicePath,
00334                   This->DriverBindingHandle,
00335                   Controller,
00336                   EFI_OPEN_PROTOCOL_BY_DRIVER
00337                   );
00338   if (EFI_ERROR (Status)) {
00339     goto Done;
00340   }
00341 
00342   Status = gBS->OpenProtocol (
00343                   Controller,
00344                   &gEfiPciIoProtocolGuid,
00345                   (VOID **) &PciIo,
00346                   This->DriverBindingHandle,
00347                   Controller,
00348                   EFI_OPEN_PROTOCOL_BY_DRIVER
00349                   );
00350   if (EFI_ERROR (Status)) {
00351     goto Done;
00352   }
00353 
00354   Status = PciIo->Attributes (
00355                     PciIo,
00356                     EfiPciIoAttributeOperationSupported,
00357                     0,
00358                     &Supports
00359                     );
00360   if (!EFI_ERROR (Status)) {
00361     Supports &= EFI_PCI_DEVICE_ENABLE;
00362     Status = PciIo->Attributes (
00363                       PciIo,
00364                       EfiPciIoAttributeOperationEnable,
00365                       Supports,
00366                       NULL
00367                       );
00368   }
00369 
00370   if (EFI_ERROR (Status)) {
00371     goto Done;
00372   }
00373   //
00374   // Check to see if there is a legacy option ROM image associated with this PCI device
00375   //
00376   Status = LegacyBios->CheckPciRom (
00377                          LegacyBios,
00378                          Controller,
00379                          NULL,
00380                          NULL,
00381                          &Flags
00382                          );
00383   if (EFI_ERROR (Status)) {
00384     goto Done;
00385   }
00386   //
00387   // Post the legacy option ROM if it is available.
00388   //
00389   Status = LegacyBios->InstallPciRom (
00390                          LegacyBios,
00391                          Controller,
00392                          NULL,
00393                          &Flags,
00394                          NULL,
00395                          NULL,
00396                          NULL,
00397                          NULL
00398                          );
00399   if (EFI_ERROR (Status)) {
00400     goto Done;
00401   }
00402   //
00403   // Allocate memory for this SimpleNetwork device instance
00404   //
00405   Status = gBS->AllocatePool (
00406                   EfiBootServicesData,
00407                   sizeof (EFI_SIMPLE_NETWORK_DEV),
00408                   (VOID **) &SimpleNetworkDevice
00409                   );
00410   if (EFI_ERROR (Status)) {
00411     Status = EFI_OUT_OF_RESOURCES;
00412     goto Done;
00413   }
00414 
00415   ZeroMem (SimpleNetworkDevice, sizeof (EFI_SIMPLE_NETWORK_DEV));
00416 
00417   //
00418   // Initialize the SimpleNetwork device instance
00419   //
00420   SimpleNetworkDevice->Signature      = EFI_SIMPLE_NETWORK_DEV_SIGNATURE;
00421   SimpleNetworkDevice->LegacyBios     = LegacyBios;
00422   SimpleNetworkDevice->BaseDevicePath = DevicePath;
00423   SimpleNetworkDevice->PciIo          = PciIo;
00424 
00425   //
00426   // Initialize the Nii Protocol
00427   //
00428   SimpleNetworkDevice->Nii.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;
00429   SimpleNetworkDevice->Nii.Type     = EfiNetworkInterfaceUndi;
00430 
00431   CopyMem (&SimpleNetworkDevice->Nii.StringId, "UNDI", 4);
00432 
00433   //
00434   // Load 16 bit UNDI Option ROM into Memory
00435   //
00436   Status = Undi16SimpleNetworkLoadUndi (SimpleNetworkDevice);
00437   if (EFI_ERROR (Status)) {
00438     DEBUG ((DEBUG_NET, "ERROR : Could not load UNDI.  Status = %r\n", Status));
00439     goto Done;
00440   }
00441 
00442   SimpleNetworkDevice->UndiLoaded = TRUE;
00443 
00444   //
00445   // Call PXENV_START_UNDI - Initilizes the UNID interface for use.
00446   //
00447   PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
00448   Status = Undi16SimpleNetworkStartUndi (
00449              SimpleNetworkDevice,
00450              (UINT16) ((Bus << 0x8) | (Device << 0x3) | (Function))
00451              );
00452   if (EFI_ERROR (Status)) {
00453     DEBUG ((DEBUG_NET, "ERROR : Could not StartUndi.  Status = %r\n", Status));
00454     goto Done;
00455   }
00456   //
00457   // Initialize the Simple Network Protocol
00458   //
00459   DEBUG ((DEBUG_NET, "Initialize SimpleNetworkDevice instance\n"));
00460 
00461   SimpleNetworkDevice->SimpleNetwork.Revision       = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
00462   SimpleNetworkDevice->SimpleNetwork.Start          = Undi16SimpleNetworkStart;
00463   SimpleNetworkDevice->SimpleNetwork.Stop           = Undi16SimpleNetworkStop;
00464   SimpleNetworkDevice->SimpleNetwork.Initialize     = Undi16SimpleNetworkInitialize;
00465   SimpleNetworkDevice->SimpleNetwork.Reset          = Undi16SimpleNetworkReset;
00466   SimpleNetworkDevice->SimpleNetwork.Shutdown       = Undi16SimpleNetworkShutdown;
00467   SimpleNetworkDevice->SimpleNetwork.ReceiveFilters = Undi16SimpleNetworkReceiveFilters;
00468   SimpleNetworkDevice->SimpleNetwork.StationAddress = Undi16SimpleNetworkStationAddress;
00469   SimpleNetworkDevice->SimpleNetwork.Statistics     = Undi16SimpleNetworkStatistics;
00470   SimpleNetworkDevice->SimpleNetwork.MCastIpToMac   = Undi16SimpleNetworkMCastIpToMac;
00471   SimpleNetworkDevice->SimpleNetwork.NvData         = Undi16SimpleNetworkNvData;
00472   SimpleNetworkDevice->SimpleNetwork.GetStatus      = Undi16SimpleNetworkGetStatus;
00473   SimpleNetworkDevice->SimpleNetwork.Transmit       = Undi16SimpleNetworkTransmit;
00474   SimpleNetworkDevice->SimpleNetwork.Receive        = Undi16SimpleNetworkReceive;
00475   SimpleNetworkDevice->SimpleNetwork.Mode           = &(SimpleNetworkDevice->SimpleNetworkMode);
00476 
00477   Status = gBS->CreateEvent (
00478                   EVT_NOTIFY_WAIT,
00479                   TPL_NOTIFY,
00480                   Undi16SimpleNetworkWaitForPacket,
00481                   &SimpleNetworkDevice->SimpleNetwork,
00482                   &SimpleNetworkDevice->SimpleNetwork.WaitForPacket
00483                   );
00484   if (EFI_ERROR (Status)) {
00485     DEBUG ((DEBUG_ERROR, "ERROR : Could not create event.  Status = %r\n", Status));
00486     goto Done;
00487   }
00488   //
00489   // Create an event to be signalled when ExitBootServices occurs in order
00490   // to clean up nicely
00491   //
00492   Status = gBS->CreateEventEx (
00493                   EVT_NOTIFY_SIGNAL,
00494                   TPL_NOTIFY,
00495                   Undi16SimpleNetworkEvent,
00496                   NULL,
00497                   &gEfiEventExitBootServicesGuid,
00498                   &SimpleNetworkDevice->EfiBootEvent
00499                   );
00500   if (EFI_ERROR (Status)) {
00501     DEBUG ((DEBUG_ERROR, "ERROR : Could not create event.  Status = %r\n", Status));
00502     goto Done;
00503   }
00504 
00505   //
00506   // Create an event to be signalled when Legacy Boot occurs to clean up the IVT
00507   //
00508   Status = EfiCreateEventLegacyBootEx(
00509              TPL_NOTIFY, 
00510              Undi16SimpleNetworkEvent, 
00511              NULL, 
00512              &SimpleNetworkDevice->LegacyBootEvent
00513              );
00514   
00515   if (EFI_ERROR(Status)) {
00516     DEBUG ((DEBUG_ERROR,"ERROR : Could not create event.  Status = %r\n",Status));
00517     goto Done;
00518   }
00519 
00520   //
00521   // Initialize the SimpleNetwork Mode Information
00522   //
00523   DEBUG ((DEBUG_NET, "Initialize Mode Information\n"));
00524 
00525   SimpleNetworkDevice->SimpleNetworkMode.State                = EfiSimpleNetworkStopped;
00526   SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize      = 14;
00527   SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable = TRUE;
00528   SimpleNetworkDevice->SimpleNetworkMode.MultipleTxSupported  = TRUE;
00529   SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
00530     EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
00531     EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
00532     EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS |
00533     EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
00534   SimpleNetworkDevice->SimpleNetworkMode.MaxMCastFilterCount = MAXNUM_MCADDR;
00535 
00536   //
00537   // Initialize the SimpleNetwork Private Information
00538   //
00539   DEBUG ((DEBUG_NET, "Initialize Private Information\n"));
00540 
00541   Status = BiosSnp16AllocatePagesBelowOneMb (
00542              sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1,
00543              (VOID **) &SimpleNetworkDevice->Xmit
00544              );
00545   if (EFI_ERROR (Status)) {
00546     goto Done;
00547   }
00548 
00549   Status = BiosSnp16AllocatePagesBelowOneMb (
00550              1,
00551              &SimpleNetworkDevice->TxRealModeMediaHeader
00552              );
00553   if (EFI_ERROR (Status)) {
00554     goto Done;
00555   }
00556 
00557   Status = BiosSnp16AllocatePagesBelowOneMb (
00558              1,
00559              &SimpleNetworkDevice->TxRealModeDataBuffer
00560              );
00561   if (EFI_ERROR (Status)) {
00562     goto Done;
00563   }
00564 
00565   Status = BiosSnp16AllocatePagesBelowOneMb (
00566              1,
00567              &SimpleNetworkDevice->TxDestAddr
00568              );
00569   if (EFI_ERROR (Status)) {
00570     goto Done;
00571   }
00572 
00573   SimpleNetworkDevice->Xmit->XmitOffset               = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeMediaHeader) & 0x000f);
00574 
00575   SimpleNetworkDevice->Xmit->XmitSegment              = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeMediaHeader) >> 4);
00576 
00577   SimpleNetworkDevice->Xmit->DataBlkCount             = 1;
00578 
00579   SimpleNetworkDevice->Xmit->DataBlock[0].TDPtrType   = 1;
00580   SimpleNetworkDevice->Xmit->DataBlock[0].TDRsvdByte  = 0;
00581 
00582   SimpleNetworkDevice->Xmit->DataBlock[0].TDDataPtrOffset = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeDataBuffer) & 0x000f);
00583 
00584   SimpleNetworkDevice->Xmit->DataBlock[0].TDDataPtrSegment = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeDataBuffer) >> 4);
00585 
00586   SimpleNetworkDevice->TxBufferFifo.First = 0;
00587   SimpleNetworkDevice->TxBufferFifo.Last  = 0;
00588 
00589   //
00590   // Start() the SimpleNetwork device
00591   //
00592   DEBUG ((DEBUG_NET, "Start()\n"));
00593 
00594   Status = Undi16SimpleNetworkStart (&SimpleNetworkDevice->SimpleNetwork);
00595   if (EFI_ERROR (Status)) {
00596     goto Done;
00597   }
00598   //
00599   // GetInformation() the SimpleNetwork device
00600   //
00601   DEBUG ((DEBUG_NET, "GetInformation()\n"));
00602 
00603   Status = Undi16SimpleNetworkGetInformation (&SimpleNetworkDevice->SimpleNetwork);
00604   if (EFI_ERROR (Status)) {
00605     goto Done;
00606   }
00607   //
00608   // Build the device path for the child device
00609   //
00610   ZeroMem (&Node, sizeof (Node));
00611   Node.DevPath.Type     = MESSAGING_DEVICE_PATH;
00612   Node.DevPath.SubType  = MSG_MAC_ADDR_DP;
00613   SetDevicePathNodeLength (&Node.DevPath, sizeof (MAC_ADDR_DEVICE_PATH));
00614   CopyMem (
00615     &Node.MacAddr.MacAddress,
00616     &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
00617     sizeof (EFI_MAC_ADDRESS)
00618     );
00619   SimpleNetworkDevice->DevicePath = AppendDevicePathNode (
00620                                       SimpleNetworkDevice->BaseDevicePath,
00621                                       &Node.DevPath
00622                                       );
00623 
00624   //
00625   // GetNicType()  the SimpleNetwork device
00626   //
00627   DEBUG ((DEBUG_NET, "GetNicType()\n"));
00628 
00629   Status = Undi16SimpleNetworkGetNicType (&SimpleNetworkDevice->SimpleNetwork);
00630   if (EFI_ERROR (Status)) {
00631     goto Done;
00632   }
00633   //
00634   // GetNdisInfo() the SimpleNetwork device
00635   //
00636   DEBUG ((DEBUG_NET, "GetNdisInfo()\n"));
00637 
00638   Status = Undi16SimpleNetworkGetNdisInfo (&SimpleNetworkDevice->SimpleNetwork);
00639   if (EFI_ERROR (Status)) {
00640     goto Done;
00641   }
00642   //
00643   // Stop() the SimpleNetwork device
00644   //
00645   DEBUG ((DEBUG_NET, "Stop()\n"));
00646 
00647   Status = SimpleNetworkDevice->SimpleNetwork.Stop (&SimpleNetworkDevice->SimpleNetwork);
00648   if (EFI_ERROR (Status)) {
00649     goto Done;
00650   }
00651   //
00652   // Print Mode information
00653   //
00654   DEBUG ((DEBUG_NET, "Mode->State                = %d\n", SimpleNetworkDevice->SimpleNetworkMode.State));
00655   DEBUG ((DEBUG_NET, "Mode->HwAddressSize        = %d\n", SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize));
00656   DEBUG ((DEBUG_NET, "Mode->MacAddressChangeable = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable));
00657   DEBUG ((DEBUG_NET, "Mode->MultiplTxSupported   = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MultipleTxSupported));
00658   DEBUG ((DEBUG_NET, "Mode->NvRamSize            = %d\n", SimpleNetworkDevice->SimpleNetworkMode.NvRamSize));
00659   DEBUG ((DEBUG_NET, "Mode->NvRamAccessSize      = %d\n", SimpleNetworkDevice->SimpleNetworkMode.NvRamAccessSize));
00660   DEBUG ((DEBUG_NET, "Mode->ReceiveFilterSetting = %d\n", SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting));
00661   DEBUG ((DEBUG_NET, "Mode->IfType               = %d\n", SimpleNetworkDevice->SimpleNetworkMode.IfType));
00662   DEBUG ((DEBUG_NET, "Mode->MCastFilterCount     = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount));
00663   for (Index = 0; Index < SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount; Index++) {
00664     DEBUG ((DEBUG_NET, "  Filter[%02d] = ", Index));
00665     for (Index2 = 0; Index2 < 16; Index2++) {
00666       DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index].Addr[Index2]));
00667     }
00668 
00669     DEBUG ((DEBUG_NET, "\n"));
00670   }
00671 
00672   DEBUG ((DEBUG_NET, "CurrentAddress = "));
00673   for (Index2 = 0; Index2 < 16; Index2++) {
00674     DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress.Addr[Index2]));
00675   }
00676 
00677   DEBUG ((DEBUG_NET, "\n"));
00678 
00679   DEBUG ((DEBUG_NET, "BroadcastAddress = "));
00680   for (Index2 = 0; Index2 < 16; Index2++) {
00681     DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress.Addr[Index2]));
00682   }
00683 
00684   DEBUG ((DEBUG_NET, "\n"));
00685 
00686   DEBUG ((DEBUG_NET, "PermanentAddress = "));
00687   for (Index2 = 0; Index2 < 16; Index2++) {
00688     DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress.Addr[Index2]));
00689   }
00690 
00691   DEBUG ((DEBUG_NET, "\n"));
00692 
00693   //
00694   // The network device was started, information collected, and stopped.
00695   // Install protocol interfaces for the SimpleNetwork device.
00696   //
00697   DEBUG ((DEBUG_NET, "Install Protocol Interfaces on network interface\n"));
00698 
00699   Status = gBS->InstallMultipleProtocolInterfaces (
00700                   &SimpleNetworkDevice->Handle,
00701                   &gEfiSimpleNetworkProtocolGuid,
00702                   &SimpleNetworkDevice->SimpleNetwork,
00703                   &gEfiNetworkInterfaceIdentifierProtocolGuid,
00704                   &SimpleNetworkDevice->Nii,
00705                   &gEfiDevicePathProtocolGuid,
00706                   SimpleNetworkDevice->DevicePath,
00707                   NULL
00708                   );
00709   if (EFI_ERROR (Status)) {
00710     goto Done;
00711   }
00712   //
00713   // Open PCI I/O from the newly created child handle
00714   //
00715   Status = gBS->OpenProtocol (
00716                   Controller,
00717                   &gEfiPciIoProtocolGuid,
00718                   (VOID **) &PciIo,
00719                   This->DriverBindingHandle,
00720                   SimpleNetworkDevice->Handle,
00721                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
00722                   );
00723 
00724   DEBUG ((DEBUG_INIT, "UNDI16 Driver : EFI_SUCCESS\n"));
00725 
00726 Done:
00727   if (EFI_ERROR (Status)) {
00728     if (SimpleNetworkDevice != NULL) {
00729 
00730       Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork);
00731       //
00732       // CLOSE + SHUTDOWN
00733       //
00734       Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice);
00735       //
00736       // CLEANUP
00737       //
00738       Undi16SimpleNetworkStopUndi (SimpleNetworkDevice);
00739       //
00740       // STOP
00741       //
00742       if (SimpleNetworkDevice->UndiLoaded) {
00743         Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);
00744       }
00745 
00746       if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket != NULL) {
00747         gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket);
00748       }
00749 
00750       if (SimpleNetworkDevice->LegacyBootEvent != NULL) {
00751         gBS->CloseEvent (SimpleNetworkDevice->LegacyBootEvent);
00752       }
00753       
00754       if (SimpleNetworkDevice->EfiBootEvent != NULL) {
00755         gBS->CloseEvent (SimpleNetworkDevice->EfiBootEvent);
00756       }
00757 
00758       if (SimpleNetworkDevice->Xmit != NULL) {
00759         gBS->FreePages (
00760                (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->Xmit,
00761                sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1
00762                );
00763       }
00764 
00765       if (SimpleNetworkDevice->TxRealModeMediaHeader != NULL) {
00766         gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeMediaHeader, 1);
00767       }
00768 
00769       if (SimpleNetworkDevice->TxRealModeDataBuffer != NULL) {
00770         gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeDataBuffer, 1);
00771       }
00772 
00773       if (SimpleNetworkDevice->TxDestAddr != NULL) {
00774         gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxDestAddr, 1);
00775       }
00776 
00777       gBS->FreePool (SimpleNetworkDevice);
00778       
00779       //
00780       //  Only restore the vector if it was cached.
00781       //
00782       if (mCachedInt1A) {
00783         RestoreCachedVectorAddress (0x1A);
00784         mCachedInt1A = FALSE;
00785       }
00786     }
00787 
00788     if (PciIo != NULL) {
00789       Status = PciIo->Attributes (
00790                         PciIo,
00791                         EfiPciIoAttributeOperationSupported,
00792                         0,
00793                         &Supports
00794                         );
00795       if (!EFI_ERROR (Status)) {
00796         Supports &= EFI_PCI_DEVICE_ENABLE;
00797         Status = PciIo->Attributes (
00798                           PciIo,
00799                           EfiPciIoAttributeOperationDisable,
00800                           Supports,
00801                           NULL
00802                           );
00803       }
00804     }
00805 
00806     gBS->CloseProtocol (
00807            Controller,
00808            &gEfiPciIoProtocolGuid,
00809            This->DriverBindingHandle,
00810            Controller
00811            );
00812 
00813     gBS->CloseProtocol (
00814            Controller,
00815            &gEfiDevicePathProtocolGuid,
00816            This->DriverBindingHandle,
00817            Controller
00818            );
00819     if (Status != EFI_OUT_OF_RESOURCES) {
00820       Status = EFI_DEVICE_ERROR;
00821     }
00822   }  
00823   return Status;
00824 }
00825 
00838 EFI_STATUS
00839 EFIAPI
00840 BiosSnp16DriverBindingStop (
00841   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
00842   IN  EFI_HANDLE                      Controller,
00843   IN  UINTN                           NumberOfChildren,
00844   IN  EFI_HANDLE                      *ChildHandleBuffer
00845   )
00846 {
00847   EFI_STATUS                  Status;
00848   UINTN                       Index;
00849   BOOLEAN                     AllChildrenStopped;
00850   EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork;
00851   EFI_SIMPLE_NETWORK_DEV      *SimpleNetworkDevice;
00852   EFI_PCI_IO_PROTOCOL         *PciIo;
00853   UINT64                      Supports;
00854 
00855   //
00856   // Complete all outstanding transactions to Controller.
00857   // Don't allow any new transaction to Controller to be started.
00858   //
00859   if (NumberOfChildren == 0) {
00860     //
00861     // Close the bus driver
00862     //
00863     Status = gBS->OpenProtocol (
00864                     Controller,
00865                     &gEfiPciIoProtocolGuid,
00866                     (VOID **) &PciIo,
00867                     This->DriverBindingHandle,
00868                     Controller,
00869                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
00870                     );
00871     if (!EFI_ERROR (Status)) {
00872       Status = PciIo->Attributes (
00873                         PciIo,
00874                         EfiPciIoAttributeOperationSupported,
00875                         0,
00876                         &Supports
00877                         );
00878       if (!EFI_ERROR (Status)) {
00879         Supports &= EFI_PCI_DEVICE_ENABLE;
00880         Status = PciIo->Attributes (
00881                           PciIo,
00882                           EfiPciIoAttributeOperationDisable,
00883                           Supports,
00884                           NULL
00885                           );
00886       }
00887     }
00888 
00889     Status = gBS->CloseProtocol (
00890                     Controller,
00891                     &gEfiPciIoProtocolGuid,
00892                     This->DriverBindingHandle,
00893                     Controller
00894                     );
00895 
00896     Status = gBS->CloseProtocol (
00897                     Controller,
00898                     &gEfiDevicePathProtocolGuid,
00899                     This->DriverBindingHandle,
00900                     Controller
00901                     );
00902                     
00903     if (EFI_ERROR (Status)) {
00904       Status = EFI_DEVICE_ERROR;
00905     }
00906     return Status;
00907   }
00908 
00909   AllChildrenStopped = TRUE;
00910 
00911   for (Index = 0; Index < NumberOfChildren; Index++) {
00912 
00913     Status = gBS->OpenProtocol (
00914                     ChildHandleBuffer[Index],
00915                     &gEfiSimpleNetworkProtocolGuid,
00916                     (VOID **) &SimpleNetwork,
00917                     This->DriverBindingHandle,
00918                     Controller,
00919                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
00920                     );
00921     if (!EFI_ERROR (Status)) {
00922 
00923       SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SimpleNetwork);
00924 
00925       Status = gBS->CloseProtocol (
00926                       Controller,
00927                       &gEfiPciIoProtocolGuid,
00928                       This->DriverBindingHandle,
00929                       ChildHandleBuffer[Index]
00930                       );
00931 
00932       Status = gBS->UninstallMultipleProtocolInterfaces (
00933                       SimpleNetworkDevice->Handle,
00934                       &gEfiSimpleNetworkProtocolGuid,
00935                       &SimpleNetworkDevice->SimpleNetwork,
00936                       &gEfiNetworkInterfaceIdentifierProtocolGuid,
00937                       &SimpleNetworkDevice->Nii,
00938                       &gEfiDevicePathProtocolGuid,
00939                       SimpleNetworkDevice->DevicePath,
00940                       NULL
00941                       );
00942       if (EFI_ERROR (Status)) {
00943         gBS->OpenProtocol (
00944                Controller,
00945                &gEfiPciIoProtocolGuid,
00946                (VOID **) &PciIo,
00947                This->DriverBindingHandle,
00948                ChildHandleBuffer[Index],
00949                EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
00950                );
00951       } else {
00952 
00953         Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork);
00954         //
00955         // CLOSE + SHUTDOWN
00956         //
00957         Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice);
00958         //
00959         // CLEANUP
00960         //
00961         Undi16SimpleNetworkStopUndi (SimpleNetworkDevice);
00962         //
00963         // STOP
00964         //
00965         if (SimpleNetworkDevice->UndiLoaded) {
00966           Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);
00967         }
00968 
00969         if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket != NULL) {
00970           gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket);
00971         }
00972 
00973         if (SimpleNetworkDevice->LegacyBootEvent != NULL) {
00974           gBS->CloseEvent (SimpleNetworkDevice->LegacyBootEvent);
00975         }
00976       
00977         if (SimpleNetworkDevice->EfiBootEvent != NULL) {
00978           gBS->CloseEvent (SimpleNetworkDevice->EfiBootEvent);
00979         }
00980 
00981         if (SimpleNetworkDevice->Xmit != NULL) {
00982           gBS->FreePages (
00983                  (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->Xmit,
00984                  sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1
00985                  );
00986         }
00987 
00988         if (SimpleNetworkDevice->TxRealModeMediaHeader != NULL) {
00989           gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeMediaHeader, 1);
00990         }
00991 
00992         if (SimpleNetworkDevice->TxRealModeDataBuffer != NULL) {
00993           gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeDataBuffer, 1);
00994         }
00995 
00996         if (SimpleNetworkDevice->TxDestAddr != NULL) {
00997           gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxDestAddr, 1);
00998         }
00999 
01000         gBS->FreePool (SimpleNetworkDevice);
01001       }
01002 
01003     }
01004 
01005     if (EFI_ERROR (Status)) {
01006       AllChildrenStopped = FALSE;
01007     }
01008   }
01009 
01010   if (!AllChildrenStopped) {
01011     return EFI_DEVICE_ERROR;
01012   }
01013 
01014   return EFI_SUCCESS;
01015 }
01016 
01017 //
01018 // FIFO Support Functions
01019 //
01027 BOOLEAN
01028 SimpleNetworkTransmitFifoFull (
01029   EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo
01030   )
01031 {
01032   if (((Fifo->Last + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE) == Fifo->First) {
01033     return TRUE;
01034   }
01035 
01036   return FALSE;
01037 }
01038 
01046 BOOLEAN
01047 SimpleNetworkTransmitFifoEmpty (
01048   EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo
01049   )
01050 {
01051   if (Fifo->Last == Fifo->First) {
01052     return TRUE;
01053   }
01054 
01055   return FALSE;
01056 }
01057 
01058 
01068 EFI_STATUS
01069 SimpleNetworkTransmitFifoAdd (
01070   EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo,
01071   VOID                        *Data
01072   )
01073 {
01074   if (SimpleNetworkTransmitFifoFull (Fifo)) {
01075     return EFI_OUT_OF_RESOURCES;
01076   }
01077 
01078   Fifo->Data[Fifo->Last]  = Data;
01079   Fifo->Last              = (Fifo->Last + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE;
01080   return EFI_SUCCESS;
01081 }
01082 
01092 EFI_STATUS
01093 SimpleNetworkTransmitFifoRemove (
01094   EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo,
01095   VOID                        **Data
01096   )
01097 {
01098   if (SimpleNetworkTransmitFifoEmpty (Fifo)) {
01099     return EFI_OUT_OF_RESOURCES;
01100   }
01101 
01102   *Data       = Fifo->Data[Fifo->First];
01103   Fifo->First = (Fifo->First + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE;
01104   return EFI_SUCCESS;
01105 }
01106 
01114 UINT16
01115 Undi16GetPacketFilterSetting (
01116   UINTN ReceiveFilterSetting
01117   )
01118 {
01119   UINT16  PktFilter;
01120 
01121   PktFilter = 0;
01122   if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) {
01123     PktFilter |= FLTR_DIRECTED;
01124   }
01125 
01126   if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
01127     PktFilter |= FLTR_DIRECTED;
01128   }
01129 
01130   if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {
01131     PktFilter |= FLTR_BRDCST;
01132   }
01133 
01134   if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
01135     PktFilter |= FLTR_PRMSCS;
01136   }
01137 
01138   if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
01139     PktFilter |= FLTR_PRMSCS;
01140     //
01141     // @bug : Do not know if this is right????
01142     //
01143   }
01144   //
01145   // @bug : What is FLTR_SRC_RTG?
01146   //
01147   return PktFilter;
01148 }
01149 
01158 VOID
01159 Undi16GetMCastFilters (
01160   IN EFI_SIMPLE_NETWORK_MODE      *Mode,
01161   IN OUT PXENV_UNDI_MCAST_ADDR_T  *McastBuffer,
01162   IN UINTN                        HwAddressSize
01163   )
01164 {
01165   UINTN Index;
01166 
01167   //
01168   // @bug : What if Mode->MCastFilterCount > MAXNUM_MCADDR?
01169   //
01170   McastBuffer->MCastAddrCount = (UINT16) Mode->MCastFilterCount;
01171   for (Index = 0; Index < MAXNUM_MCADDR; Index++) {
01172     if (Index < McastBuffer->MCastAddrCount) {
01173       CopyMem (&McastBuffer->MCastAddr[Index], &Mode->MCastFilter[Index], HwAddressSize);
01174     } else {
01175       ZeroMem (&McastBuffer->MCastAddr[Index], HwAddressSize);
01176     }
01177   }
01178 }
01179 //
01180 // Load 16 bit UNDI Option ROM into memory
01181 //
01190 EFI_STATUS
01191 Undi16SimpleNetworkLoadUndi (
01192   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
01193   )
01194 {
01195   EFI_STATUS                Status;
01196   EFI_PCI_IO_PROTOCOL       *PciIo;
01197   UINTN                     RomAddress;
01198   PCI_EXPANSION_ROM_HEADER  *PciExpansionRomHeader;
01199   PCI_DATA_STRUCTURE        *PciDataStructure;
01200   PCI_TYPE00                Pci;
01201   
01202   if (!mCachedInt1A) {
01203     Status = CacheVectorAddress (0x1A);
01204     if (!EFI_ERROR (Status)) {
01205       mCachedInt1A = TRUE;    
01206     }
01207   }
01208 
01209   PciIo = SimpleNetworkDevice->PciIo;
01210 
01211   PciIo->Pci.Read (
01212                PciIo,
01213                EfiPciIoWidthUint32,
01214                0,
01215                sizeof (Pci) / sizeof (UINT32),
01216                &Pci
01217                );
01218 
01219   for (RomAddress = 0xc0000; RomAddress < 0xfffff; RomAddress += 0x800) {
01220 
01221     PciExpansionRomHeader = (PCI_EXPANSION_ROM_HEADER *) RomAddress;
01222 
01223     if (PciExpansionRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
01224       continue;
01225     }
01226 
01227     DEBUG ((DEBUG_INIT, "Option ROM found at %X\n", RomAddress));
01228 
01229     PciDataStructure = (PCI_DATA_STRUCTURE *) (RomAddress + PciExpansionRomHeader->PcirOffset);
01230 
01231     if (PciDataStructure->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
01232       continue;
01233     }
01234 
01235     DEBUG ((DEBUG_INIT, "PCI Data Structure found at %X\n", PciDataStructure));
01236 
01237     if (PciDataStructure->VendorId != Pci.Hdr.VendorId || PciDataStructure->DeviceId != Pci.Hdr.DeviceId) {
01238       continue;
01239     }
01240 
01241     DEBUG (
01242         (DEBUG_INIT, 
01243          "PCI device with matchinng VendorId and DeviceId (%d,%d)\n",
01244          (UINTN) PciDataStructure->VendorId,
01245          (UINTN) PciDataStructure->DeviceId)
01246         );
01247 
01248     Status = LaunchBaseCode (SimpleNetworkDevice, RomAddress);
01249 
01250     if (!EFI_ERROR (Status)) {
01251       return EFI_SUCCESS;
01252     }
01253   }
01254 
01255   return EFI_NOT_FOUND;
01256 }
01257 
01265 EFI_STATUS
01266 Undi16SimpleNetworkUnloadUndi (
01267   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
01268   )
01269 {
01270   if (SimpleNetworkDevice->UndiLoaderTable != NULL) {
01271     ZeroMem (SimpleNetworkDevice->UndiLoaderTable, SimpleNetworkDevice->UndiLoaderTablePages << EFI_PAGE_SHIFT);
01272     gBS->FreePages (
01273           (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->UndiLoaderTable,
01274           SimpleNetworkDevice->UndiLoaderTablePages
01275           );
01276   }
01277 
01278   if (SimpleNetworkDevice->DestinationDataSegment != NULL) {
01279     ZeroMem (
01280       SimpleNetworkDevice->DestinationDataSegment,
01281       SimpleNetworkDevice->DestinationDataSegmentPages << EFI_PAGE_SHIFT
01282       );
01283     gBS->FreePages (
01284           (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationDataSegment,
01285           SimpleNetworkDevice->DestinationDataSegmentPages
01286           );
01287   }
01288 
01289   if (SimpleNetworkDevice->DestinationStackSegment != NULL) {
01290     ZeroMem (
01291       SimpleNetworkDevice->DestinationStackSegment,
01292       SimpleNetworkDevice->DestinationStackSegmentPages << EFI_PAGE_SHIFT
01293       );
01294     gBS->FreePages (
01295           (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationStackSegment,
01296           SimpleNetworkDevice->DestinationStackSegmentPages
01297           );
01298   }
01299 
01300   if (SimpleNetworkDevice->DestinationCodeSegment != NULL) {
01301     ZeroMem (
01302       SimpleNetworkDevice->DestinationCodeSegment,
01303       SimpleNetworkDevice->DestinationCodeSegmentPages << EFI_PAGE_SHIFT
01304       );
01305     gBS->FreePages (
01306           (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationCodeSegment,
01307           SimpleNetworkDevice->DestinationCodeSegmentPages
01308           );
01309   }
01310 
01311   return EFI_SUCCESS;
01312 }
01313 
01323 EFI_STATUS
01324 Undi16SimpleNetworkStartUndi (
01325   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice,
01326   UINT16                  Ax
01327   )
01328 {
01329   EFI_STATUS          Status;
01330   PXENV_START_UNDI_T  Start;
01331 
01332   //
01333   // Call 16 bit UNDI ROM to start the network interface
01334   //
01335   //
01336   // @bug : What is this state supposed to be???
01337   //
01338   Start.Status  = INIT_PXE_STATUS;
01339   Start.Ax      = Ax;
01340   Start.Bx      = 0x0000;
01341   Start.Dx      = 0x0000;
01342   Start.Di      = 0x0000;
01343   Start.Es      = 0x0000;
01344 
01345   Status        = PxeStartUndi (SimpleNetworkDevice, &Start);
01346   if (EFI_ERROR (Status)) {
01347     return Status;
01348   }
01349   //
01350   // Check the status code from the 16 bit UNDI ROM
01351   //
01352   if (Start.Status != PXENV_STATUS_SUCCESS) {
01353     return EFI_DEVICE_ERROR;
01354   }
01355 
01356   return Status;
01357 }
01358 
01359 
01368 EFI_STATUS
01369 Undi16SimpleNetworkStopUndi (
01370   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
01371   )
01372 {
01373   EFI_STATUS        Status;
01374   PXENV_STOP_UNDI_T Stop;
01375 
01376   //
01377   // Call 16 bit UNDI ROM to start the network interface
01378   //
01379   Stop.Status = INIT_PXE_STATUS;
01380 
01381   Status      = PxeUndiStop (SimpleNetworkDevice, &Stop);
01382   if (EFI_ERROR (Status)) {
01383     return Status;
01384   }
01385   //
01386   // Check the status code from the 16 bit UNDI ROM
01387   //
01388   if (Stop.Status != PXENV_STATUS_SUCCESS) {
01389     return EFI_DEVICE_ERROR;
01390   }
01391 
01392   return Status;
01393 }
01394 
01403 EFI_STATUS
01404 Undi16SimpleNetworkCleanupUndi (
01405   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice
01406   )
01407 {
01408   EFI_STATUS            Status;
01409   PXENV_UNDI_CLEANUP_T  Cleanup;
01410 
01411   //
01412   // Call 16 bit UNDI ROM to cleanup the network interface
01413   //
01414   Cleanup.Status  = INIT_PXE_STATUS;
01415 
01416   Status          = PxeUndiCleanup (SimpleNetworkDevice, &Cleanup);
01417   if (EFI_ERROR (Status)) {
01418     return Status;
01419   }
01420   //
01421   // Check the status code from the 16 bit UNDI ROM
01422   //
01423   if (Cleanup.Status != PXENV_STATUS_SUCCESS) {
01424     return EFI_DEVICE_ERROR;
01425   }
01426 
01427   return Status;
01428 }
01429 
01438 EFI_STATUS
01439 Undi16SimpleNetworkGetInformation (
01440   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
01441   )
01442 {
01443   EFI_STATUS              Status;
01444   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
01445   UINTN                   Index;
01446 
01447   if (This == NULL) {
01448     return EFI_INVALID_PARAMETER;
01449   }
01450 
01451   Status              = EFI_SUCCESS;
01452   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
01453 
01454   if (SimpleNetworkDevice == NULL) {
01455     return EFI_DEVICE_ERROR;
01456   }
01457   //
01458   // Verify that the current state of the adapter is valid for this call.
01459   //
01460   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
01461   case EfiSimpleNetworkStarted:
01462   case EfiSimpleNetworkInitialized:
01463     break;
01464 
01465   case EfiSimpleNetworkStopped:
01466     return EFI_NOT_STARTED;
01467 
01468   default:
01469     return EFI_DEVICE_ERROR;
01470   }
01471   //
01472   // Call 16 bit UNDI ROM to start the network interface
01473   //
01474   ZeroMem (&SimpleNetworkDevice->GetInformation, sizeof (PXENV_UNDI_GET_INFORMATION_T));
01475 
01476   SimpleNetworkDevice->GetInformation.Status  = INIT_PXE_STATUS;
01477 
01478   Status = PxeUndiGetInformation (SimpleNetworkDevice, &SimpleNetworkDevice->GetInformation);
01479   if (EFI_ERROR (Status)) {
01480     return Status;
01481   }
01482 
01483   DEBUG ((DEBUG_NET, "  GetInformation.Status      = %d\n", SimpleNetworkDevice->GetInformation.Status));
01484   DEBUG ((DEBUG_NET, "  GetInformation.BaseIo      = %d\n", SimpleNetworkDevice->GetInformation.BaseIo));
01485   DEBUG ((DEBUG_NET, "  GetInformation.IntNumber   = %d\n", SimpleNetworkDevice->GetInformation.IntNumber));
01486   DEBUG ((DEBUG_NET, "  GetInformation.MaxTranUnit = %d\n", SimpleNetworkDevice->GetInformation.MaxTranUnit));
01487   DEBUG ((DEBUG_NET, "  GetInformation.HwType      = %d\n", SimpleNetworkDevice->GetInformation.HwType));
01488   DEBUG ((DEBUG_NET, "  GetInformation.HwAddrLen   = %d\n", SimpleNetworkDevice->GetInformation.HwAddrLen));
01489   DEBUG ((DEBUG_NET, "  GetInformation.ROMAddress  = %d\n", SimpleNetworkDevice->GetInformation.ROMAddress));
01490   DEBUG ((DEBUG_NET, "  GetInformation.RxBufCt     = %d\n", SimpleNetworkDevice->GetInformation.RxBufCt));
01491   DEBUG ((DEBUG_NET, "  GetInformation.TxBufCt     = %d\n", SimpleNetworkDevice->GetInformation.TxBufCt));
01492 
01493   DEBUG ((DEBUG_NET, "  GetInformation.CurNodeAddr ="));
01494   for (Index = 0; Index < 16; Index++) {
01495     DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->GetInformation.CurrentNodeAddress[Index]));
01496   }
01497 
01498   DEBUG ((DEBUG_NET, "\n"));
01499 
01500   DEBUG ((DEBUG_NET, "  GetInformation.PermNodeAddr ="));
01501   for (Index = 0; Index < 16; Index++) {
01502     DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->GetInformation.PermNodeAddress[Index]));
01503   }
01504 
01505   DEBUG ((DEBUG_NET, "\n"));
01506 
01507   //
01508   // Check the status code from the 16 bit UNDI ROM
01509   //
01510   if (SimpleNetworkDevice->GetInformation.Status != PXENV_STATUS_SUCCESS) {
01511     return EFI_DEVICE_ERROR;
01512   }
01513   //
01514   // The information has been retrieved.  Fill in Mode data.
01515   //
01516   SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize  = SimpleNetworkDevice->GetInformation.HwAddrLen;
01517 
01518   SimpleNetworkDevice->SimpleNetworkMode.MaxPacketSize  = SimpleNetworkDevice->GetInformation.MaxTranUnit;
01519 
01520   SimpleNetworkDevice->SimpleNetworkMode.IfType         = (UINT8) SimpleNetworkDevice->GetInformation.HwType;
01521 
01522   ZeroMem (
01523     &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
01524     sizeof SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress
01525     );
01526 
01527   CopyMem (
01528     &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
01529     &SimpleNetworkDevice->GetInformation.CurrentNodeAddress,
01530     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
01531     );
01532 
01533   ZeroMem (
01534     &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
01535     sizeof SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress
01536     );
01537 
01538   CopyMem (
01539     &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
01540     &SimpleNetworkDevice->GetInformation.PermNodeAddress,
01541     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
01542     );
01543 
01544   //
01545   // hard code broadcast address - not avail in PXE2.1
01546   //
01547   ZeroMem (
01548     &SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress,
01549     sizeof SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress
01550     );
01551 
01552   SetMem (
01553     &SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress,
01554     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize,
01555     0xff
01556     );
01557 
01558   return Status;
01559 }
01560 
01569 EFI_STATUS
01570 Undi16SimpleNetworkGetNicType (
01571   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
01572   )
01573 {
01574   EFI_STATUS              Status;
01575   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
01576 
01577   if (This == NULL) {
01578     return EFI_INVALID_PARAMETER;
01579   }
01580 
01581   Status              = EFI_SUCCESS;
01582   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
01583 
01584   if (SimpleNetworkDevice == NULL) {
01585     return EFI_DEVICE_ERROR;
01586   }
01587 
01588   ZeroMem (&SimpleNetworkDevice->GetNicType, sizeof (PXENV_UNDI_GET_NIC_TYPE_T));
01589 
01590   SimpleNetworkDevice->GetNicType.Status  = INIT_PXE_STATUS;
01591 
01592   Status = PxeUndiGetNicType (SimpleNetworkDevice, &SimpleNetworkDevice->GetNicType);
01593 
01594   if (EFI_ERROR (Status)) {
01595     return Status;
01596   }
01597 
01598   DEBUG ((DEBUG_NET, "  GetNicType.Status      = %d\n", SimpleNetworkDevice->GetNicType.Status));
01599   DEBUG ((DEBUG_NET, "  GetNicType.NicType     = %d\n", SimpleNetworkDevice->GetNicType.NicType));
01600   //
01601   // Check the status code from the 16 bit UNDI ROM
01602   //
01603   if (SimpleNetworkDevice->GetNicType.Status != PXENV_STATUS_SUCCESS) {
01604     return EFI_DEVICE_ERROR;
01605   }
01606   //
01607   // The information has been retrieved.  Fill in Mode data.
01608   //
01609   return Status;
01610 }
01611 
01620 EFI_STATUS
01621 Undi16SimpleNetworkGetNdisInfo (
01622   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
01623   )
01624 {
01625   EFI_STATUS              Status;
01626   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
01627 
01628   if (This == NULL) {
01629     return EFI_INVALID_PARAMETER;
01630   }
01631 
01632   Status              = EFI_SUCCESS;
01633   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
01634 
01635   if (SimpleNetworkDevice == NULL) {
01636     return EFI_DEVICE_ERROR;
01637   }
01638 
01639   ZeroMem (&SimpleNetworkDevice->GetNdisInfo, sizeof (PXENV_UNDI_GET_NDIS_INFO_T));
01640 
01641   SimpleNetworkDevice->GetNdisInfo.Status = INIT_PXE_STATUS;
01642 
01643   Status = PxeUndiGetNdisInfo (SimpleNetworkDevice, &SimpleNetworkDevice->GetNdisInfo);
01644 
01645   if (EFI_ERROR (Status)) {
01646     return Status;
01647   }
01648 
01649   DEBUG ((DEBUG_NET, "  GetNdisInfo.Status       = %d\n", SimpleNetworkDevice->GetNdisInfo.Status));
01650   DEBUG ((DEBUG_NET, "  GetNdisInfo.IfaceType    = %a\n", SimpleNetworkDevice->GetNdisInfo.IfaceType));
01651   DEBUG ((DEBUG_NET, "  GetNdisInfo.LinkSpeed    = %d\n", SimpleNetworkDevice->GetNdisInfo.LinkSpeed));
01652   DEBUG ((DEBUG_NET, "  GetNdisInfo.ServiceFlags = %08x\n", SimpleNetworkDevice->GetNdisInfo.ServiceFlags));
01653 
01654   //
01655   // Check the status code from the 16 bit UNDI ROM
01656   //
01657   if (SimpleNetworkDevice->GetNdisInfo.Status != PXENV_STATUS_SUCCESS) {
01658     return EFI_DEVICE_ERROR;
01659   }
01660   //
01661   // The information has been retrieved.  Fill in Mode data.
01662   //
01663   return Status;
01664 }
01665 
01679 EFI_STATUS
01680 Undi16SimpleNetworkIsr (
01681   IN EFI_SIMPLE_NETWORK_PROTOCOL * This,
01682   IN UINTN                       *FrameLength,
01683   IN UINTN                       *FrameHeaderLength, OPTIONAL
01684   IN UINT8                       *Frame, OPTIONAL
01685   IN UINT8                       *ProtType, OPTIONAL
01686   IN UINT8                       *PktType OPTIONAL
01687   )
01688 {
01689   EFI_STATUS              Status;
01690   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
01691   BOOLEAN                 FrameReceived;
01692 
01693   if (This == NULL) {
01694     return EFI_INVALID_PARAMETER;
01695   }
01696 
01697   Status              = EFI_SUCCESS;
01698   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
01699 
01700   if (SimpleNetworkDevice == NULL) {
01701     return EFI_DEVICE_ERROR;
01702   }
01703 
01704   FrameReceived = FALSE;
01705 
01706   //
01707   // Verify that the current state of the adapter is valid for this call.
01708   //
01709   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
01710   case EfiSimpleNetworkInitialized:
01711     break;
01712 
01713   case EfiSimpleNetworkStopped:
01714     return EFI_NOT_STARTED;
01715 
01716   case EfiSimpleNetworkStarted:
01717   default:
01718     return EFI_DEVICE_ERROR;
01719   }
01720 
01721   DEBUG ((DEBUG_NET, "Isr() IsrValid = %d\n", SimpleNetworkDevice->IsrValid));
01722 
01723   if (!SimpleNetworkDevice->IsrValid) {
01724     //
01725     // Call 16 bit UNDI ROM to open the network interface
01726     //
01727     ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));
01728     SimpleNetworkDevice->Isr.Status   = INIT_PXE_STATUS;
01729     SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_START;
01730 
01731     DEBUG ((DEBUG_NET, "Isr() START\n"));
01732 
01733     Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
01734     if (EFI_ERROR (Status)) {
01735       return Status;
01736     }
01737     //
01738     // Check the status code from the 16 bit UNDI ROM
01739     //
01740     if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
01741       return EFI_DEVICE_ERROR;
01742     }
01743     //
01744     // There have been no events on this UNDI interface, so return EFI_NOT_READY
01745     //
01746     if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_NOT_OURS) {
01747       return EFI_SUCCESS;
01748     }
01749     //
01750     // There is data to process, so call until all events processed.
01751     //
01752     ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));
01753     SimpleNetworkDevice->Isr.Status   = INIT_PXE_STATUS;
01754     SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
01755 
01756     DEBUG ((DEBUG_NET, "Isr() PROCESS\n"));
01757 
01758     Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
01759     if (EFI_ERROR (Status)) {
01760       return Status;
01761     }
01762 
01763     SimpleNetworkDevice->IsrValid = TRUE;
01764   }
01765   //
01766   // Call UNDI GET_NEXT until DONE
01767   //
01768   while (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_DONE) {
01769     //
01770     // Check the status code from the 16 bit UNDI ROM
01771     //
01772     if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
01773       return EFI_DEVICE_ERROR;
01774     }
01775     //
01776     // UNDI is busy.  Caller will have to call again.
01777     // This should never happen with a polled mode driver.
01778     //
01779     if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_BUSY) {
01780       DEBUG ((DEBUG_NET, "  BUSY\n"));
01781       return EFI_SUCCESS;
01782     }
01783     //
01784     // Check for invalud UNDI FuncFlag
01785     //
01786     if (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_RECEIVE &&
01787         SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_TRANSMIT
01788         ) {
01789       DEBUG ((DEBUG_NET, "  Invalid SimpleNetworkDevice->Isr.FuncFlag value %d\n", SimpleNetworkDevice->Isr.FuncFlag));
01790       return EFI_DEVICE_ERROR;
01791     }
01792     //
01793     // Check for Transmit Event
01794     //
01795     if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_TRANSMIT) {
01796       DEBUG ((DEBUG_NET, "  TRANSMIT\n"));
01797       SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
01798     }
01799     //
01800     // Check for Receive Event
01801     //
01802     else if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_RECEIVE) {
01803       //
01804       // note - this code will hang on a receive interrupt in a GetStatus loop
01805       //
01806       DEBUG ((DEBUG_NET, "  RECEIVE\n"));
01807       SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
01808 
01809       DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.BufferLength      = %d\n", SimpleNetworkDevice->Isr.BufferLength));
01810       DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.FrameLength       = %d\n", SimpleNetworkDevice->Isr.FrameLength));
01811       DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.FrameHeaderLength = %d\n", SimpleNetworkDevice->Isr.FrameHeaderLength));
01812       DEBUG (
01813         (
01814         DEBUG_NET, "SimpleNetworkDevice->Isr.Frame             = %04x:%04x\n", SimpleNetworkDevice->Isr.FrameSegSel,
01815         SimpleNetworkDevice->Isr.FrameOffset
01816         )
01817         );
01818       DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.ProtType          = 0x%02x\n", SimpleNetworkDevice->Isr.BufferLength));
01819       DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.PktType           = 0x%02x\n", SimpleNetworkDevice->Isr.BufferLength));
01820 
01821       if (FrameReceived) {
01822         return EFI_SUCCESS;
01823       }
01824 
01825       if ((Frame == NULL) || (SimpleNetworkDevice->Isr.FrameLength > *FrameLength)) {
01826         DEBUG ((DEBUG_NET, "return EFI_BUFFER_TOO_SMALL   *FrameLength = %08x\n", *FrameLength));
01827         *FrameLength = SimpleNetworkDevice->Isr.FrameLength;
01828         return EFI_BUFFER_TOO_SMALL;
01829       }
01830 
01831       *FrameLength = SimpleNetworkDevice->Isr.FrameLength;
01832       if (FrameHeaderLength != NULL) {
01833         *FrameHeaderLength = SimpleNetworkDevice->Isr.FrameHeaderLength;
01834       }
01835 
01836       if (ProtType != NULL) {
01837         *ProtType = SimpleNetworkDevice->Isr.ProtType;
01838       }
01839 
01840       if (PktType != NULL) {
01841         *PktType = SimpleNetworkDevice->Isr.PktType;
01842       }
01843 
01844       CopyMem (
01845         Frame,
01846         (VOID *)(UINTN) ((SimpleNetworkDevice->Isr.FrameSegSel << 4) + SimpleNetworkDevice->Isr.FrameOffset),
01847         SimpleNetworkDevice->Isr.BufferLength
01848         );
01849       Frame = Frame + SimpleNetworkDevice->Isr.BufferLength;
01850       if (SimpleNetworkDevice->Isr.BufferLength == SimpleNetworkDevice->Isr.FrameLength) {
01851         FrameReceived = TRUE;
01852       }
01853     }
01854     //
01855     // There is data to process, so call until all events processed.
01856     //
01857     ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));
01858     SimpleNetworkDevice->Isr.Status   = INIT_PXE_STATUS;
01859     SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
01860 
01861     DEBUG ((DEBUG_NET, "Isr() GET NEXT\n"));
01862 
01863     Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
01864     if (EFI_ERROR (Status)) {
01865       return Status;
01866     }
01867     //
01868     // Check the status code from the 16 bit UNDI ROM
01869     //
01870     //        if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
01871     //            return EFI_DEVICE_ERROR;
01872     //        }
01873     //
01874   }
01875 
01876   SimpleNetworkDevice->IsrValid = FALSE;
01877   return EFI_SUCCESS;
01878 }
01879 //
01880 // ///////////////////////////////////////////////////////////////////////////////////////
01881 // Simple Network Protocol Interface Functions using 16 bit UNDI Option ROMs
01883 //
01884 // Start()
01885 //
01895 EFI_STATUS
01896 EFIAPI
01897 Undi16SimpleNetworkStart (
01898   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
01899   )
01900 {
01901   EFI_STATUS              Status;
01902   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
01903   PXENV_UNDI_STARTUP_T    Startup;
01904 
01905   if (This == NULL) {
01906     return EFI_INVALID_PARAMETER;
01907   }
01908 
01909   Status              = EFI_SUCCESS;
01910   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
01911 
01912   if (SimpleNetworkDevice == NULL) {
01913     return EFI_DEVICE_ERROR;
01914   }
01915   //
01916   // Verify that the current state of the adapter is valid for this call.
01917   //
01918   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
01919   case EfiSimpleNetworkStopped:
01920     break;
01921 
01922   case EfiSimpleNetworkStarted:
01923   case EfiSimpleNetworkInitialized:
01924     return EFI_ALREADY_STARTED;
01925 
01926   default:
01927     return EFI_DEVICE_ERROR;
01928   }
01929   //
01930   // Call 16 bit UNDI ROM to start the network interface
01931   //
01932   Startup.Status  = INIT_PXE_STATUS;
01933 
01934   Status          = PxeUndiStartup (SimpleNetworkDevice, &Startup);
01935   if (EFI_ERROR (Status)) {
01936     return Status;
01937   }
01938   //
01939   // Check the status code from the 16 bit UNDI ROM
01940   //
01941   if (Startup.Status != PXENV_STATUS_SUCCESS) {
01942     return EFI_DEVICE_ERROR;
01943   }
01944   //
01945   // The UNDI interface has been started, so update the State.
01946   //
01947   SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStarted;
01948 
01949   //
01950   //
01951   //
01952   SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting = 0;
01953   SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount     = 0;
01954 
01955   return Status;
01956 }
01957 //
01958 // Stop()
01959 //
01969 EFI_STATUS
01970 EFIAPI
01971 Undi16SimpleNetworkStop (
01972   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
01973   )
01974 {
01975   EFI_STATUS              Status;
01976   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
01977 
01978   if (This == NULL) {
01979     return EFI_INVALID_PARAMETER;
01980   }
01981 
01982   Status              = EFI_SUCCESS;
01983   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
01984 
01985   if (SimpleNetworkDevice == NULL) {
01986     return EFI_DEVICE_ERROR;
01987   }
01988   //
01989   // Verify that the current state of the adapter is valid for this call.
01990   //
01991   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
01992   case EfiSimpleNetworkStarted:
01993     break;
01994 
01995   case EfiSimpleNetworkStopped:
01996     return EFI_NOT_STARTED;
01997 
01998   case EfiSimpleNetworkInitialized:
01999   default:
02000     return EFI_DEVICE_ERROR;
02001   }
02002 
02003   SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStopped;
02004 
02005   return Status;
02006 }
02007 
02008 //
02009 // Initialize()
02010 //
02021 EFI_STATUS
02022 EFIAPI
02023 Undi16SimpleNetworkInitialize (
02024   IN EFI_SIMPLE_NETWORK_PROTOCOL            *This,
02025   IN UINTN                                  ExtraRxBufferSize  OPTIONAL,
02026   IN UINTN                                  ExtraTxBufferSize  OPTIONAL
02027   )
02028 {
02029   EFI_STATUS              Status;
02030   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
02031   PXENV_UNDI_INITIALIZE_T Initialize;
02032   PXENV_UNDI_OPEN_T       Open;
02033 
02034   if (This == NULL) {
02035     return EFI_INVALID_PARAMETER;
02036   }
02037 
02038   Status              = EFI_SUCCESS;
02039   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
02040 
02041   if (SimpleNetworkDevice == NULL) {
02042     return EFI_DEVICE_ERROR;
02043   }
02044   //
02045   // Verify that the current state of the adapter is valid for this call.
02046   //
02047   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
02048   case EfiSimpleNetworkStopped:
02049     return EFI_NOT_STARTED;
02050 
02051   case EfiSimpleNetworkStarted:
02052     break;
02053 
02054   case EfiSimpleNetworkInitialized:
02055   default:
02056     return EFI_DEVICE_ERROR;
02057   }
02058   //
02059   // Call 16 bit UNDI ROM to start the network interface
02060   //
02061   Initialize.Status       = INIT_PXE_STATUS;
02062   Initialize.ProtocolIni  = 0;
02063 
02064   Status                  = PxeUndiInitialize (SimpleNetworkDevice, &Initialize);
02065 
02066   if (EFI_ERROR (Status)) {
02067     DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiInitialize() - Status = %r\n", Status));
02068     DEBUG ((DEBUG_ERROR, "Initialize.Status == %xh\n", Initialize.Status));
02069 
02070     if (Initialize.Status == PXENV_STATUS_UNDI_MEDIATEST_FAILED) {
02071       Status = EFI_NO_MEDIA;
02072     }
02073 
02074     return Status;
02075   }
02076   //
02077   // Check the status code from the 16 bit UNDI ROM
02078   //
02079   if (Initialize.Status != PXENV_STATUS_SUCCESS) {
02080     DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiInitialize() - Initialize.Status = %04x\n", Initialize.Status));
02081     return EFI_DEVICE_ERROR;
02082   }
02083   //
02084   // Call 16 bit UNDI ROM to open the network interface
02085   //
02086   Open.Status     = INIT_PXE_STATUS;
02087   Open.OpenFlag   = 0;
02088   Open.PktFilter  = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);
02089   Undi16GetMCastFilters (
02090     &SimpleNetworkDevice->SimpleNetworkMode,
02091     &Open.McastBuffer,
02092     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
02093     );
02094 
02095   Status = PxeUndiOpen (SimpleNetworkDevice, &Open);
02096 
02097   if (EFI_ERROR (Status)) {
02098     DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiOpen() - Status = %r\n", Status));
02099     return Status;
02100   }
02101   //
02102   // Check the status code from the 16 bit UNDI ROM
02103   //
02104   if (Open.Status != PXENV_STATUS_SUCCESS) {
02105     DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiOpen() - Open.Status = %04x\n", Open.Status));
02106     return EFI_DEVICE_ERROR;
02107   }
02108   //
02109   // The UNDI interface has been initialized, so update the State.
02110   //
02111   SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkInitialized;
02112 
02113   //
02114   // If initialize succeeds, then assume that media is present.
02115   //
02116   SimpleNetworkDevice->SimpleNetworkMode.MediaPresent = TRUE;
02117 
02118   //
02119   // Reset the recycled transmit buffer FIFO
02120   //
02121   SimpleNetworkDevice->TxBufferFifo.First = 0;
02122   SimpleNetworkDevice->TxBufferFifo.Last  = 0;
02123   SimpleNetworkDevice->IsrValid           = FALSE;
02124 
02125   return Status;
02126 }
02127 //
02128 // Reset()
02129 //
02142 EFI_STATUS
02143 EFIAPI
02144 Undi16SimpleNetworkReset (
02145   IN EFI_SIMPLE_NETWORK_PROTOCOL   *This,
02146   IN BOOLEAN                       ExtendedVerification
02147   )
02148 {
02149   EFI_STATUS              Status;
02150   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
02151   PXENV_UNDI_RESET_T      Reset;
02152   UINT16                  Rx_filter;
02153 
02154   if (This == NULL) {
02155     return EFI_INVALID_PARAMETER;
02156   }
02157 
02158   Status              = EFI_SUCCESS;
02159   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
02160 
02161   if (SimpleNetworkDevice == NULL) {
02162     return EFI_DEVICE_ERROR;
02163   }
02164   //
02165   // Verify that the current state of the adapter is valid for this call.
02166   //
02167   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
02168   case EfiSimpleNetworkStopped:
02169     return EFI_NOT_STARTED;
02170 
02171   case EfiSimpleNetworkInitialized:
02172     break;
02173 
02174   case EfiSimpleNetworkStarted:
02175   default:
02176     return EFI_DEVICE_ERROR;
02177   }
02178 
02179   Reset.Status  = INIT_PXE_STATUS;
02180 
02181   Rx_filter     = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);
02182 
02183   Undi16GetMCastFilters (
02184     &SimpleNetworkDevice->SimpleNetworkMode,
02185     &Reset.R_Mcast_Buf,
02186     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
02187     );
02188 
02189   Status = PxeUndiResetNic (SimpleNetworkDevice, &Reset, Rx_filter);
02190 
02191   if (EFI_ERROR (Status)) {
02192     return Status;
02193   }
02194   //
02195   // Check the status code from the 16 bit UNDI ROM
02196   //
02197   if (Reset.Status != PXENV_STATUS_SUCCESS) {
02198     return EFI_DEVICE_ERROR;
02199   }
02200   //
02201   // Reset the recycled transmit buffer FIFO
02202   //
02203   SimpleNetworkDevice->TxBufferFifo.First = 0;
02204   SimpleNetworkDevice->TxBufferFifo.Last  = 0;
02205   SimpleNetworkDevice->IsrValid           = FALSE;
02206 
02207   return Status;
02208 }
02209 //
02210 // Shutdown()
02211 //
02223 EFI_STATUS
02224 EFIAPI
02225 Undi16SimpleNetworkShutdown (
02226   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
02227   )
02228 {
02229   EFI_STATUS              Status;
02230   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
02231   PXENV_UNDI_CLOSE_T      Close;
02232   PXENV_UNDI_SHUTDOWN_T   Shutdown;
02233 
02234   if (This == NULL) {
02235     return EFI_INVALID_PARAMETER;
02236   }
02237 
02238   Status              = EFI_SUCCESS;
02239   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
02240 
02241   if (SimpleNetworkDevice == NULL) {
02242     return EFI_DEVICE_ERROR;
02243   }
02244   //
02245   // Verify that the current state of the adapter is valid for this call.
02246   //
02247   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
02248   case EfiSimpleNetworkStopped:
02249     return EFI_NOT_STARTED;
02250 
02251   case EfiSimpleNetworkInitialized:
02252     break;
02253 
02254   case EfiSimpleNetworkStarted:
02255   default:
02256     return EFI_DEVICE_ERROR;
02257   }
02258 
02259   SimpleNetworkDevice->IsrValid = FALSE;
02260 
02261   //
02262   // Call 16 bit UNDI ROM to start the network interface
02263   //
02264   Close.Status  = INIT_PXE_STATUS;
02265 
02266   Status        = PxeUndiClose (SimpleNetworkDevice, &Close);
02267 
02268   if (EFI_ERROR (Status)) {
02269     return Status;
02270   }
02271   //
02272   // Check the status code from the 16 bit UNDI ROM
02273   //
02274   if (Close.Status != PXENV_STATUS_SUCCESS) {
02275     return EFI_DEVICE_ERROR;
02276   }
02277   //
02278   // Call 16 bit UNDI ROM to open the network interface
02279   //
02280   Shutdown.Status = INIT_PXE_STATUS;
02281 
02282   Status          = PxeUndiShutdown (SimpleNetworkDevice, &Shutdown);
02283 
02284   if (EFI_ERROR (Status)) {
02285     return Status;
02286   }
02287   //
02288   // Check the status code from the 16 bit UNDI ROM
02289   //
02290   if (Shutdown.Status != PXENV_STATUS_SUCCESS) {
02291     return EFI_DEVICE_ERROR;
02292   }
02293   //
02294   // The UNDI interface has been initialized, so update the State.
02295   //
02296   SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStarted;
02297 
02298   //
02299   // If shutdown succeeds, then assume that media is not present.
02300   //
02301   SimpleNetworkDevice->SimpleNetworkMode.MediaPresent = FALSE;
02302 
02303   //
02304   // Reset the recycled transmit buffer FIFO
02305   //
02306   SimpleNetworkDevice->TxBufferFifo.First = 0;
02307   SimpleNetworkDevice->TxBufferFifo.Last  = 0;
02308 
02309   //
02310   // A short delay.  Without this an initialize immediately following
02311   // a shutdown will cause some versions of UNDI-16 to stop operating.
02312   //
02313   gBS->Stall (250000);
02314 
02315   return Status;
02316 }
02317 //
02318 // ReceiveFilters()
02319 //
02336 EFI_STATUS
02337 EFIAPI
02338 Undi16SimpleNetworkReceiveFilters (
02339   IN EFI_SIMPLE_NETWORK_PROTOCOL                     * This,
02340   IN UINT32                                          Enable,
02341   IN UINT32                                          Disable,
02342   IN BOOLEAN                                         ResetMCastFilter,
02343   IN UINTN                                           MCastFilterCnt     OPTIONAL,
02344   IN EFI_MAC_ADDRESS                                 * MCastFilter OPTIONAL
02345   )
02346 {
02347   EFI_STATUS              Status;
02348   UINTN                   Index;
02349   UINT32                  NewFilter;
02350   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
02351   PXENV_UNDI_CLOSE_T      Close;
02352   PXENV_UNDI_OPEN_T       Open;
02353 
02354   if (This == NULL) {
02355     return EFI_INVALID_PARAMETER;
02356   }
02357 
02358   Status              = EFI_SUCCESS;
02359   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
02360 
02361   if (SimpleNetworkDevice == NULL) {
02362     return EFI_DEVICE_ERROR;
02363   }
02364   //
02365   // Verify that the current state of the adapter is valid for this call.
02366   //
02367   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
02368   case EfiSimpleNetworkStopped:
02369     return EFI_NOT_STARTED;
02370 
02371   case EfiSimpleNetworkInitialized:
02372     break;
02373 
02374   case EfiSimpleNetworkStarted:
02375   default:
02376     return EFI_DEVICE_ERROR;
02377   }
02378   //
02379   // First deal with possible filter setting changes
02380   //
02381   if ((Enable == 0) && (Disable == 0) && !ResetMCastFilter) {
02382     return EFI_SUCCESS;
02383   }
02384 
02385   NewFilter = (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting | Enable) &~Disable;
02386 
02387   if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
02388     if ((MCastFilterCnt == 0) || (MCastFilter == 0) || MCastFilterCnt > SimpleNetworkDevice->SimpleNetworkMode.MaxMCastFilterCount) {
02389       return EFI_INVALID_PARAMETER;
02390     }
02391   }
02392   //
02393   // Call 16 bit UNDI ROM to close the network interface
02394   //
02395   Close.Status  = INIT_PXE_STATUS;
02396 
02397   Status        = PxeUndiClose (SimpleNetworkDevice, &Close);
02398 
02399   if (EFI_ERROR (Status)) {
02400     return Status;
02401   }
02402   //
02403   // Check the status code from the 16 bit UNDI ROM
02404   //
02405   if (Close.Status != PXENV_STATUS_SUCCESS) {
02406     return EFI_DEVICE_ERROR;
02407   }
02408   //
02409   // Call 16 bit UNDI ROM to open the network interface
02410   //
02411   //
02412   // Reset the recycled transmit buffer FIFO
02413   //
02414   SimpleNetworkDevice->TxBufferFifo.First = 0;
02415   SimpleNetworkDevice->TxBufferFifo.Last  = 0;
02416 
02417   //
02418   // Call 16 bit UNDI ROM to open the network interface
02419   //
02420   ZeroMem (&Open, sizeof Open);
02421 
02422   Open.Status     = INIT_PXE_STATUS;
02423   Open.PktFilter  = Undi16GetPacketFilterSetting (NewFilter);
02424 
02425   if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
02426     //
02427     // Copy the MAC addresses into the UNDI open parameter structure
02428     //
02429     Open.McastBuffer.MCastAddrCount = (UINT16) MCastFilterCnt;
02430     for (Index = 0; Index < MCastFilterCnt; ++Index) {
02431       CopyMem (
02432         Open.McastBuffer.MCastAddr[Index],
02433         &MCastFilter[Index],
02434         sizeof Open.McastBuffer.MCastAddr[Index]
02435         );
02436     }
02437   } else if (!ResetMCastFilter) {
02438     for (Index = 0; Index < SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount; ++Index) {
02439       CopyMem (
02440         Open.McastBuffer.MCastAddr[Index],
02441         &SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index],
02442         sizeof Open.McastBuffer.MCastAddr[Index]
02443         );
02444     }
02445   }
02446 
02447   Status = PxeUndiOpen (SimpleNetworkDevice, &Open);
02448 
02449   if (EFI_ERROR (Status)) {
02450     return Status;
02451   }
02452   //
02453   // Check the status code from the 16 bit UNDI ROM
02454   //
02455   if (Open.Status != PXENV_STATUS_SUCCESS) {
02456     return EFI_DEVICE_ERROR;
02457   }
02458 
02459   SimpleNetworkDevice->IsrValid = FALSE;
02460   SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting = NewFilter;
02461 
02462   if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
02463     SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount = (UINT32) MCastFilterCnt;
02464     for (Index = 0; Index < MCastFilterCnt; ++Index) {
02465       CopyMem (
02466         &SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index],
02467         &MCastFilter[Index],
02468         sizeof (EFI_MAC_ADDRESS)
02469         );      
02470     }
02471   }
02472   //
02473   // Read back multicast addresses.
02474   //
02475   return EFI_SUCCESS;
02476 }
02477 //
02478 // StationAddress()
02479 //
02493 EFI_STATUS
02494 EFIAPI
02495 Undi16SimpleNetworkStationAddress (
02496   IN EFI_SIMPLE_NETWORK_PROTOCOL           * This,
02497   IN BOOLEAN                               Reset,
02498   IN EFI_MAC_ADDRESS                       * New OPTIONAL
02499   )
02500 {
02501   EFI_STATUS                    Status;
02502   EFI_SIMPLE_NETWORK_DEV        *SimpleNetworkDevice;
02503   PXENV_UNDI_SET_STATION_ADDR_T SetStationAddr;
02504   //
02505   // EFI_DEVICE_PATH_PROTOCOL     *OldDevicePath;
02506   //
02507   PXENV_UNDI_CLOSE_T            Close;
02508   PXENV_UNDI_OPEN_T             Open;
02509 
02510   if (This == NULL) {
02511     return EFI_INVALID_PARAMETER;
02512   }
02513 
02514   Status              = EFI_SUCCESS;
02515 
02516   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
02517 
02518   if (SimpleNetworkDevice == NULL) {
02519     return EFI_DEVICE_ERROR;
02520   }
02521   //
02522   // Verify that the current state of the adapter is valid for this call.
02523   //
02524   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
02525   case EfiSimpleNetworkInitialized:
02526     break;
02527 
02528   case EfiSimpleNetworkStopped:
02529     return EFI_NOT_STARTED;
02530 
02531   case EfiSimpleNetworkStarted:
02532   default:
02533     return EFI_DEVICE_ERROR;
02534   }
02535   //
02536   // Call 16 bit UNDI ROM to open the network interface
02537   //
02538   SetStationAddr.Status = INIT_PXE_STATUS;
02539 
02540   if (Reset) {
02541     //
02542     // If we are reseting the Station Address to the permanent address, and the
02543     // Station Address is not programmable, then just return EFI_SUCCESS.
02544     //
02545     if (!SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable) {
02546       return EFI_SUCCESS;
02547     }
02548     //
02549     // If the address is already the permanent address, then just return success.
02550     //
02551     if (CompareMem (
02552           &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
02553           &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
02554           SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
02555           ) == 0) {
02556       return EFI_SUCCESS;
02557     }
02558     //
02559     // Copy the adapters permanent address to the new station address
02560     //
02561     CopyMem (
02562       &SetStationAddr.StationAddress,
02563       &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
02564       SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
02565       );
02566   } else {
02567     //
02568     // If we are setting the Station Address, and the
02569     // Station Address is not programmable, return invalid parameter.
02570     //
02571     if (!SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable) {
02572       return EFI_INVALID_PARAMETER;
02573     }
02574     //
02575     // If the address is already the new address, then just return success.
02576     //
02577     if (CompareMem (
02578           &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
02579           New,
02580           SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
02581           ) == 0) {
02582       return EFI_SUCCESS;
02583     }
02584     //
02585     // Copy New to the new station address
02586     //
02587     CopyMem (
02588       &SetStationAddr.StationAddress,
02589       New,
02590       SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
02591       );
02592 
02593   }
02594   //
02595   // Call 16 bit UNDI ROM to stop the network interface
02596   //
02597   Close.Status = INIT_PXE_STATUS;
02598 
02599   PxeUndiClose (SimpleNetworkDevice, &Close);
02600 
02601   //
02602   // Call 16-bit UNDI ROM to set the station address
02603   //
02604   SetStationAddr.Status = PXENV_STATUS_SUCCESS;
02605 
02606   Status                = PxeUndiSetStationAddr (SimpleNetworkDevice, &SetStationAddr);
02607 
02608   //
02609   // Call 16-bit UNDI ROM to start the network interface
02610   //
02611   Open.Status     = PXENV_STATUS_SUCCESS;
02612   Open.OpenFlag   = 0;
02613   Open.PktFilter  = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);
02614   Undi16GetMCastFilters (
02615     &SimpleNetworkDevice->SimpleNetworkMode,
02616     &Open.McastBuffer,
02617     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
02618     );
02619 
02620   PxeUndiOpen (SimpleNetworkDevice, &Open);
02621 
02622   //
02623   // Check status from station address change
02624   //
02625   if (EFI_ERROR (Status)) {
02626     return Status;
02627   }
02628   //
02629   // Check the status code from the 16 bit UNDI ROM
02630   //
02631   if (SetStationAddr.Status != PXENV_STATUS_SUCCESS) {
02632     return EFI_DEVICE_ERROR;
02633   }
02634 
02635   CopyMem (
02636     &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
02637     &SetStationAddr.StationAddress,
02638     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
02639     );
02640 
02641 #if 0 /* The device path is based on the permanent address not the current address. */
02642   //
02643   // The station address was changed, so update the device path with the new MAC address.
02644   //
02645   OldDevicePath                   = SimpleNetworkDevice->DevicePath;
02646   SimpleNetworkDevice->DevicePath = DuplicateDevicePath (SimpleNetworkDevice->BaseDevicePath);
02647   SimpleNetworkAppendMacAddressDevicePath (
02648     &SimpleNetworkDevice->DevicePath,
02649     &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress
02650     );
02651 
02652   Status = LibReinstallProtocolInterfaces (
02653             SimpleNetworkDevice->Handle,
02654             &DevicePathProtocol,
02655             OldDevicePath,
02656             SimpleNetworkDevice->DevicePath,
02657             NULL
02658             );
02659 
02660   if (EFI_ERROR (Status)) {
02661     DEBUG ((DEBUG_ERROR, "Failed to reinstall the DevicePath protocol for the Simple Network Device\n"));
02662     DEBUG ((DEBUG_ERROR, "  Status = %r\n", Status));
02663   }
02664 
02665   FreePool (OldDevicePath);
02666 #endif /* 0 */
02667 
02668   return Status;
02669 }
02670 //
02671 // Statistics()
02672 //
02694 EFI_STATUS
02695 EFIAPI
02696 Undi16SimpleNetworkStatistics (
02697   IN EFI_SIMPLE_NETWORK_PROTOCOL       * This,
02698   IN BOOLEAN                           Reset,
02699   IN OUT UINTN                         *StatisticsSize OPTIONAL,
02700   OUT EFI_NETWORK_STATISTICS           * StatisticsTable OPTIONAL
02701   )
02702 {
02703   EFI_STATUS                    Status;
02704   EFI_SIMPLE_NETWORK_DEV        *SimpleNetworkDevice;
02705   PXENV_UNDI_CLEAR_STATISTICS_T ClearStatistics;
02706   PXENV_UNDI_GET_STATISTICS_T   GetStatistics;
02707 
02708   if (This == NULL) {
02709     return EFI_INVALID_PARAMETER;
02710   }
02711 
02712   Status              = EFI_SUCCESS;
02713   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
02714 
02715   if (SimpleNetworkDevice == NULL) {
02716     return EFI_DEVICE_ERROR;
02717   }
02718   //
02719   // Verify that the current state of the adapter is valid for this call.
02720   //
02721   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
02722   case EfiSimpleNetworkInitialized:
02723     break;
02724 
02725   case EfiSimpleNetworkStopped:
02726     return EFI_NOT_STARTED;
02727 
02728   case EfiSimpleNetworkStarted:
02729   default:
02730     return EFI_DEVICE_ERROR;
02731   }
02732 
02733   if ((StatisticsSize != NULL) && (*StatisticsSize != 0) && (StatisticsTable == NULL)) {
02734     return EFI_INVALID_PARAMETER;
02735   }
02736 
02737   //
02738   // If Reset is TRUE, then clear all the statistics.
02739   //
02740   if (Reset) {
02741 
02742     DEBUG ((DEBUG_NET, "  RESET Statistics\n"));
02743 
02744     //
02745     // Call 16 bit UNDI ROM to open the network interface
02746     //
02747     ClearStatistics.Status  = INIT_PXE_STATUS;
02748 
02749     Status                  = PxeUndiClearStatistics (SimpleNetworkDevice, &ClearStatistics);
02750 
02751     if (EFI_ERROR (Status)) {
02752       return Status;
02753     }
02754     //
02755     // Check the status code from the 16 bit UNDI ROM
02756     //
02757     if (ClearStatistics.Status != PXENV_STATUS_SUCCESS) {
02758       return EFI_DEVICE_ERROR;
02759     }
02760 
02761     DEBUG ((DEBUG_NET, "  RESET Statistics Complete"));
02762   }
02763 
02764   if (StatisticsSize != NULL) {
02765     EFI_NETWORK_STATISTICS  LocalStatisticsTable;
02766 
02767     DEBUG ((DEBUG_NET, "  GET Statistics\n"));
02768 
02769     //
02770     // If the size if valid, then see if the table is valid
02771     //
02772     if (StatisticsTable == NULL) {
02773       DEBUG ((DEBUG_NET, "  StatisticsTable is NULL\n"));
02774       return EFI_INVALID_PARAMETER;
02775     }
02776     //
02777     // Call 16 bit UNDI ROM to open the network interface
02778     //
02779     GetStatistics.Status            = INIT_PXE_STATUS;
02780     GetStatistics.XmtGoodFrames     = 0;
02781     GetStatistics.RcvGoodFrames     = 0;
02782     GetStatistics.RcvCRCErrors      = 0;
02783     GetStatistics.RcvResourceErrors = 0;
02784 
02785     Status                          = PxeUndiGetStatistics (SimpleNetworkDevice, &GetStatistics);
02786 
02787     if (EFI_ERROR (Status)) {
02788       return Status;
02789     }
02790     //
02791     // Check the status code from the 16 bit UNDI ROM
02792     //
02793     if (GetStatistics.Status != PXENV_STATUS_SUCCESS) {
02794       return EFI_DEVICE_ERROR;
02795     }
02796     //
02797     // Fill in the Statistics Table with the collected values.
02798     //
02799     SetMem (&LocalStatisticsTable, sizeof LocalStatisticsTable, 0xff);
02800 
02801     LocalStatisticsTable.TxGoodFrames     = GetStatistics.XmtGoodFrames;
02802     LocalStatisticsTable.RxGoodFrames     = GetStatistics.RcvGoodFrames;
02803     LocalStatisticsTable.RxCrcErrorFrames = GetStatistics.RcvCRCErrors;
02804     LocalStatisticsTable.RxDroppedFrames  = GetStatistics.RcvResourceErrors;
02805 
02806     CopyMem (StatisticsTable, &LocalStatisticsTable, *StatisticsSize);
02807 
02808     DEBUG (
02809       (DEBUG_NET,
02810       "  Statistics Collected : Size=%d  Buf=%08x\n",
02811       *StatisticsSize,
02812       StatisticsTable)
02813       );
02814 
02815     DEBUG ((DEBUG_NET, "  GET Statistics Complete"));
02816 
02817     if (*StatisticsSize < sizeof LocalStatisticsTable) {
02818       DEBUG ((DEBUG_NET, "  BUFFER TOO SMALL\n"));
02819       Status = EFI_BUFFER_TOO_SMALL;
02820     }
02821 
02822     *StatisticsSize = sizeof LocalStatisticsTable;
02823 
02824     return Status;
02825 
02826   }
02827 
02828   return EFI_SUCCESS;
02829 }
02830 //
02831 // MCastIpToMac()
02832 //
02850 EFI_STATUS
02851 EFIAPI
02852 Undi16SimpleNetworkMCastIpToMac (
02853   IN EFI_SIMPLE_NETWORK_PROTOCOL            *This,
02854   IN BOOLEAN                                IPv6,
02855   IN EFI_IP_ADDRESS                         *IP,
02856   OUT EFI_MAC_ADDRESS                       *MAC
02857   )
02858 {
02859   EFI_STATUS                  Status;
02860   EFI_SIMPLE_NETWORK_DEV      *SimpleNetworkDevice;
02861   PXENV_UNDI_GET_MCAST_ADDR_T GetMcastAddr;
02862 
02863   if (This == NULL || IP == NULL || MAC == NULL) {
02864     return EFI_INVALID_PARAMETER;
02865   }
02866 
02867   Status              = EFI_SUCCESS;
02868   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
02869 
02870   if (SimpleNetworkDevice == NULL) {
02871     return EFI_DEVICE_ERROR;
02872   }
02873   //
02874   // Verify that the current state of the adapter is valid for this call.
02875   //
02876   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
02877   case EfiSimpleNetworkStopped:
02878     return EFI_NOT_STARTED;
02879 
02880   case EfiSimpleNetworkInitialized:
02881     break;
02882 
02883   case EfiSimpleNetworkStarted:
02884   default:
02885     return EFI_DEVICE_ERROR;
02886   }
02887   //
02888   // 16 bit UNDI Option ROMS do not support IPv6.  Check for IPv6 usage.
02889   //
02890   if (IPv6) {
02891     return EFI_UNSUPPORTED;
02892   }
02893   //
02894   // Call 16 bit UNDI ROM to open the network interface
02895   //
02896   GetMcastAddr.Status = INIT_PXE_STATUS;
02897   CopyMem (&GetMcastAddr.InetAddr, IP, 4);
02898 
02899   Status = PxeUndiGetMcastAddr (SimpleNetworkDevice, &GetMcastAddr);
02900 
02901   if (EFI_ERROR (Status)) {
02902     return Status;
02903   }
02904   //
02905   // Check the status code from the 16 bit UNDI ROM
02906   //
02907   if (GetMcastAddr.Status != PXENV_STATUS_SUCCESS) {
02908     return EFI_DEVICE_ERROR;
02909   }
02910   //
02911   // Copy the MAC address from the returned data structure.
02912   //
02913   CopyMem (
02914     MAC,
02915     &GetMcastAddr.MediaAddr,
02916     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
02917     );
02918 
02919   return Status;
02920 }
02921 //
02922 // NvData()
02923 //
02944 EFI_STATUS
02945 EFIAPI
02946 Undi16SimpleNetworkNvData (
02947   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This,
02948   IN BOOLEAN                      ReadWrite,
02949   IN UINTN                        Offset,
02950   IN UINTN                        BufferSize,
02951   IN OUT VOID                     *Buffer
02952   )
02953 {
02954   return EFI_UNSUPPORTED;
02955 }
02956 //
02957 // GetStatus()
02958 //
02984 EFI_STATUS
02985 EFIAPI
02986 Undi16SimpleNetworkGetStatus (
02987   IN EFI_SIMPLE_NETWORK_PROTOCOL  * This,
02988   OUT UINT32                      *InterruptStatus OPTIONAL,
02989   OUT VOID                        **TxBuf OPTIONAL
02990   )
02991 {
02992   EFI_STATUS              Status;
02993   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
02994   UINTN                   FrameLength;
02995 
02996   if (This == NULL) {
02997     return EFI_INVALID_PARAMETER;
02998   }
02999 
03000   Status              = EFI_SUCCESS;
03001   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
03002 
03003   if (SimpleNetworkDevice == NULL) {
03004     return EFI_DEVICE_ERROR;
03005   }
03006   //
03007   // Verify that the current state of the adapter is valid for this call.
03008   //
03009   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
03010   case EfiSimpleNetworkInitialized:
03011     break;
03012 
03013   case EfiSimpleNetworkStopped:
03014     return EFI_NOT_STARTED;
03015 
03016   case EfiSimpleNetworkStarted:
03017   default:
03018     return EFI_DEVICE_ERROR;
03019   }
03020 
03021   if (InterruptStatus == NULL && TxBuf == NULL) {
03022     return EFI_INVALID_PARAMETER;
03023   }
03024 
03025   FrameLength = 0;
03026   Status      = Undi16SimpleNetworkIsr (This, &FrameLength, NULL, NULL, NULL, NULL);
03027 
03028   if (Status != EFI_BUFFER_TOO_SMALL) {
03029     if (EFI_ERROR (Status)) {
03030       return Status;
03031     }
03032   }
03033   //
03034   // See if the caller wants interrupt info.
03035   //
03036   if (InterruptStatus != NULL) {
03037     *InterruptStatus                      = SimpleNetworkDevice->InterruptStatus;
03038     SimpleNetworkDevice->InterruptStatus  = 0;
03039   }
03040   //
03041   // See if the caller wants transmit buffer status info.
03042   //
03043   if (TxBuf != NULL) {
03044     *TxBuf = 0;
03045     SimpleNetworkTransmitFifoRemove (&(SimpleNetworkDevice->TxBufferFifo), TxBuf);
03046   }
03047 
03048   return EFI_SUCCESS;
03049 }
03050 
03084 EFI_STATUS
03085 EFIAPI
03086 Undi16SimpleNetworkTransmit (
03087   IN EFI_SIMPLE_NETWORK_PROTOCOL           *This,
03088   IN UINTN                                 HeaderSize,
03089   IN UINTN                                 BufferSize,
03090   IN VOID                                  *Buffer,
03091   IN EFI_MAC_ADDRESS                       *SrcAddr OPTIONAL,
03092   IN EFI_MAC_ADDRESS                       *DestAddr OPTIONAL,
03093   IN UINT16                                *Protocol OPTIONAL
03094   )
03095 {
03096   EFI_STATUS              Status;
03097   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
03098   PXENV_UNDI_TRANSMIT_T   XmitInfo;
03099 
03100   if (This == NULL) {
03101     return EFI_INVALID_PARAMETER;
03102   }
03103 
03104   Status              = EFI_SUCCESS;
03105   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
03106 
03107   if (SimpleNetworkDevice == NULL) {
03108     return EFI_DEVICE_ERROR;
03109   }
03110   //
03111   // Verify that the current state of the adapter is valid for this call.
03112   //
03113   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
03114   case EfiSimpleNetworkInitialized:
03115     break;
03116 
03117   case EfiSimpleNetworkStopped:
03118     return EFI_NOT_STARTED;
03119 
03120   case EfiSimpleNetworkStarted:
03121   default:
03122     return EFI_DEVICE_ERROR;
03123   }
03124 
03125   if (Buffer == NULL) {
03126     return EFI_INVALID_PARAMETER;
03127   }
03128 
03129   if (BufferSize < SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize) {
03130     return EFI_BUFFER_TOO_SMALL;
03131   }
03132 
03133   if (HeaderSize != 0) {
03134     if (HeaderSize != SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize) {
03135       return EFI_INVALID_PARAMETER;
03136     }
03137 
03138     if (DestAddr == NULL || Protocol == NULL) {
03139       return EFI_INVALID_PARAMETER;
03140     }
03141 
03142     if (DestAddr != NULL) {
03143       CopyMem (
03144         Buffer,
03145         DestAddr,
03146         SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
03147         );
03148     }
03149 
03150     if (SrcAddr == NULL) {
03151       SrcAddr = &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress;
03152     }
03153 
03154     CopyMem (
03155       (UINT8 *) Buffer + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize,
03156       SrcAddr,
03157       SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
03158       );
03159 
03160     if (Protocol != NULL) {
03161       *(UINT16 *) ((UINT8 *) Buffer + 2 * SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize) = (UINT16) (((*Protocol & 0xFF) << 8) | ((*Protocol >> 8) & 0xFF));
03162     }
03163   }
03164   //
03165   // See if the recycled transmit buffer FIFO is full.
03166   // If it is full, then we can not transmit until the caller calls GetStatus() to pull
03167   // off recycled transmit buffers.
03168   //
03169   if (SimpleNetworkTransmitFifoFull (&(SimpleNetworkDevice->TxBufferFifo))) {
03170     return EFI_NOT_READY;
03171   }
03172   //
03173   //  Output debug trace message.
03174   //
03175   DEBUG ((DEBUG_NET, "Undi16SimpleNetworkTransmit\n\r "));
03176 
03177   //
03178   // Initialize UNDI WRITE parameter structure.
03179   //
03180   XmitInfo.Status           = INIT_PXE_STATUS;
03181   XmitInfo.Protocol         = P_UNKNOWN;
03182   XmitInfo.XmitFlag         = XMT_DESTADDR;
03183   XmitInfo.DestAddrOffset   = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->TxDestAddr & 0x000f);
03184   XmitInfo.DestAddrSegment  = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->TxDestAddr >> 4);
03185   XmitInfo.TBDOffset        = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->Xmit & 0x000f);
03186   XmitInfo.TBDSegment       = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->Xmit >> 4);
03187   XmitInfo.Reserved[0]      = 0;
03188   XmitInfo.Reserved[1]      = 0;
03189 
03190   CopyMem (
03191     SimpleNetworkDevice->TxDestAddr,
03192     Buffer,
03193     SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
03194     );
03195 
03196   CopyMem (
03197     SimpleNetworkDevice->TxRealModeMediaHeader,
03198     Buffer,
03199     SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize
03200     );
03201 
03202   SimpleNetworkDevice->Xmit->ImmedLength            = (UINT16) SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize;
03203 
03204   SimpleNetworkDevice->Xmit->DataBlock[0].TDDataLen = (UINT16) (BufferSize - SimpleNetworkDevice->Xmit->ImmedLength);
03205 
03206   CopyMem (
03207     SimpleNetworkDevice->TxRealModeDataBuffer,
03208     (UINT8 *) Buffer + SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize,
03209     SimpleNetworkDevice->Xmit->DataBlock[0].TDDataLen
03210     );
03211 
03212   //
03213   // Make API call to UNDI TRANSMIT
03214   //
03215   XmitInfo.Status = 0;
03216 
03217   Status          = PxeUndiTransmit (SimpleNetworkDevice, &XmitInfo);
03218 
03219   if (EFI_ERROR (Status)) {
03220     return Status;
03221   }
03222   //
03223   // Check the status code from the 16 bit UNDI ROM
03224   //
03225   switch (XmitInfo.Status) {
03226   case PXENV_STATUS_OUT_OF_RESOURCES:
03227     return EFI_NOT_READY;
03228 
03229   case PXENV_STATUS_SUCCESS:
03230     break;
03231 
03232   default:
03233     return EFI_DEVICE_ERROR;
03234   }
03235   //
03236   // Add address of Buffer to the recycled transmit buffer FIFO
03237   //
03238   SimpleNetworkTransmitFifoAdd (&(SimpleNetworkDevice->TxBufferFifo), Buffer);
03239 
03240   return EFI_SUCCESS;
03241 }
03242 
03275 EFI_STATUS
03276 EFIAPI
03277 Undi16SimpleNetworkReceive (
03278   IN EFI_SIMPLE_NETWORK_PROTOCOL            *This,
03279   OUT UINTN                                 *HeaderSize OPTIONAL,
03280   IN OUT UINTN                              *BufferSize,
03281   OUT VOID                                  *Buffer,
03282   OUT EFI_MAC_ADDRESS                       *SrcAddr OPTIONAL,
03283   OUT EFI_MAC_ADDRESS                       *DestAddr OPTIONAL,
03284   OUT UINT16                                *Protocol OPTIONAL
03285   )
03286 {
03287   EFI_STATUS              Status;
03288   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
03289   UINTN                   MediaAddrSize;
03290   UINT8                   ProtType;
03291 
03292   if (This == NULL || BufferSize == NULL || Buffer == NULL) {
03293     return EFI_INVALID_PARAMETER;
03294   }
03295 
03296   Status              = EFI_SUCCESS;
03297   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
03298 
03299   if (SimpleNetworkDevice == NULL) {
03300     return EFI_DEVICE_ERROR;
03301   }
03302   //
03303   // Verify that the current state of the adapter is valid for this call.
03304   //
03305   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
03306   case EfiSimpleNetworkInitialized:
03307     break;
03308 
03309   case EfiSimpleNetworkStopped:
03310     return EFI_NOT_STARTED;
03311 
03312   case EfiSimpleNetworkStarted:
03313   default:
03314     return EFI_DEVICE_ERROR;
03315   }
03316 
03317   Status = Undi16SimpleNetworkIsr (
03318             This,
03319             BufferSize,
03320             HeaderSize,
03321             Buffer,
03322             &ProtType,
03323             NULL
03324             );
03325 
03326   if (EFI_ERROR (Status)) {
03327     return Status;
03328   }
03329 
03330   if ((SimpleNetworkDevice->InterruptStatus & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT) == 0) {
03331     return EFI_NOT_READY;
03332 
03333   }
03334 
03335   SimpleNetworkDevice->InterruptStatus &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
03336 
03337   MediaAddrSize = This->Mode->HwAddressSize;
03338 
03339   if (SrcAddr != NULL) {
03340     CopyMem (SrcAddr, (UINT8 *) Buffer + MediaAddrSize, MediaAddrSize);
03341   }
03342 
03343   if (DestAddr != NULL) {
03344     CopyMem (DestAddr, Buffer, MediaAddrSize);
03345   }
03346 
03347   if (Protocol != NULL) {
03348     *((UINT8 *) Protocol)     = *((UINT8 *) Buffer + (2 * MediaAddrSize) + 1);
03349     *((UINT8 *) Protocol + 1) = *((UINT8 *) Buffer + (2 * MediaAddrSize));
03350   }
03351 
03352   DEBUG ((DEBUG_NET, "Packet Received: BufferSize=%d  HeaderSize = %d\n", *BufferSize, *HeaderSize));
03353 
03354   return Status;
03355 
03356 }
03357 //
03358 // WaitForPacket()
03359 //
03367 VOID
03368 EFIAPI
03369 Undi16SimpleNetworkWaitForPacket (
03370   IN EFI_EVENT               Event,
03371   IN VOID                    *Context
03372   )
03373 {
03374   //
03375   // Someone is waiting on the receive packet event, if there's
03376   // a packet pending, signal the event
03377   //
03378   if (!EFI_ERROR (Undi16SimpleNetworkCheckForPacket (Context))) {
03379     gBS->SignalEvent (Event);
03380   }
03381 }
03382 //
03383 // CheckForPacket()
03384 //
03399 EFI_STATUS
03400 Undi16SimpleNetworkCheckForPacket (
03401   IN EFI_SIMPLE_NETWORK_PROTOCOL *This
03402   )
03403 {
03404   EFI_STATUS              Status;
03405   EFI_SIMPLE_NETWORK_DEV  *SimpleNetworkDevice;
03406   UINTN                   FrameLength;
03407 
03408   if (This == NULL) {
03409     return EFI_INVALID_PARAMETER;
03410   }
03411 
03412   Status              = EFI_SUCCESS;
03413   SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
03414 
03415   if (SimpleNetworkDevice == NULL) {
03416     return EFI_DEVICE_ERROR;
03417   }
03418   //
03419   // Verify that the current state of the adapter is valid for this call.
03420   //
03421   switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
03422   case EfiSimpleNetworkInitialized:
03423     break;
03424 
03425   case EfiSimpleNetworkStopped:
03426     return EFI_NOT_STARTED;
03427 
03428   case EfiSimpleNetworkStarted:
03429   default:
03430     return EFI_DEVICE_ERROR;
03431   }
03432 
03433   FrameLength = 0;
03434   Status = Undi16SimpleNetworkIsr (
03435             This,
03436             &FrameLength,
03437             NULL,
03438             NULL,
03439             NULL,
03440             NULL
03441             );
03442 
03443   if (Status != EFI_BUFFER_TOO_SMALL) {
03444     if (EFI_ERROR (Status)) {
03445       return Status;
03446     }
03447   }
03448 
03449   return ((SimpleNetworkDevice->InterruptStatus & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT) != 0) ? EFI_SUCCESS : EFI_NOT_READY;
03450 }
03451 
03460 VOID
03461 EFIAPI
03462 Undi16SimpleNetworkEvent (
03463   IN EFI_EVENT        Event,
03464   IN VOID             *Context
03465   )
03466 {
03467   //
03468   // NOTE:  This is not the only way to effect this cleanup.  The prescribed mechanism
03469   //        would be to perform an UNDI STOP command.  This strategam has been attempted
03470   //        but results in problems making some of the EFI core services from TPL_CALLBACK.
03471   //        This issue needs to be resolved, but the other alternative has been to perform
03472   //        the unchain logic explicitly, as done below.
03473   //
03474   RestoreCachedVectorAddress (0x1A);
03475 }
03476 
03485 EFI_STATUS
03486 BiosSnp16AllocatePagesBelowOneMb (
03487   UINTN  NumPages,
03488   VOID   **Buffer
03489   )
03490 {
03491   EFI_STATUS            Status;
03492   EFI_PHYSICAL_ADDRESS  PhysicalAddress;
03493 
03494   PhysicalAddress = 0x000fffff;
03495   Status = gBS->AllocatePages (
03496                   AllocateMaxAddress,
03497                   EfiRuntimeServicesData,
03498                   NumPages,
03499                   &PhysicalAddress
03500                   );
03501   if (EFI_ERROR (Status)) {
03502     return Status;
03503   }
03504 
03505   *Buffer = (VOID *) (UINTN) PhysicalAddress;
03506   return EFI_SUCCESS;
03507 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines