2 Implementation of driver entry point and driver binding protocol.
4 Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed
6 and made available under the terms and conditions of the BSD License which
7 accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 // Module global variables needed to support undi 3.0 interface
20 EFI_PCI_IO_PROTOCOL
*mPciIo
;
21 V2P
*mV2p
= NULL
; // undi3.0 map_list head
22 // End Global variables
26 One notified function to stop UNDI device when gBS->ExitBootServices() called.
28 @param Event Pointer to this event
29 @param Context Event hanlder private data
34 SnpNotifyExitBootServices (
41 Snp
= (SNP_DRIVER
*)Context
;
44 // Shutdown and stop UNDI driver
51 Send command to UNDI. It does nothing currently.
53 @param Cdb command to be sent to UNDI.
55 @retval EFI_INVALID_PARAMETER The command is 0.
56 @retval EFI_UNSUPPORTED Default return status because it's not
66 DEBUG ((EFI_D_ERROR
, "\nIssueHwUndiCommand() - This should not be called!"));
69 return EFI_INVALID_PARAMETER
;
73 // %%TBD - For now, nothing is done.
75 return EFI_UNSUPPORTED
;
80 Compute 8-bit checksum of a buffer.
82 @param Buffer Pointer to buffer.
83 @param Length Length of buffer in bytes.
85 @return 8-bit checksum of all bytes in buffer, or zero if ptr is NULL or len
101 if (Ptr
== NULL
|| Length
== 0) {
105 while (Length
-- != 0) {
106 Cksum
= (UINT8
) (Cksum
+ *Ptr
++);
113 Test to see if this driver supports ControllerHandle. This service
114 is called by the EFI boot service ConnectController(). In
115 order to make drivers as small as possible, there are a few calling
116 restrictions for this service. ConnectController() must
117 follow these calling restrictions. If any other agent wishes to call
118 Supported() it must also follow these calling restrictions.
120 @param This Protocol instance pointer.
121 @param ControllerHandle Handle of device to test.
122 @param RemainingDevicePath Optional parameter use to pick a specific child
125 @retval EFI_SUCCESS This driver supports this device.
126 @retval EFI_ALREADY_STARTED This driver is already running on this device.
127 @retval other This driver does not support this device.
132 SimpleNetworkDriverSupported (
133 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
134 IN EFI_HANDLE Controller
,
135 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
139 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL
*NiiProtocol
;
142 Status
= gBS
->OpenProtocol (
144 &gEfiDevicePathProtocolGuid
,
146 This
->DriverBindingHandle
,
148 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
150 if (EFI_ERROR (Status
)) {
154 Status
= gBS
->OpenProtocol (
156 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
157 (VOID
**) &NiiProtocol
,
158 This
->DriverBindingHandle
,
160 EFI_OPEN_PROTOCOL_BY_DRIVER
163 if (EFI_ERROR (Status
)) {
164 if (Status
== EFI_ALREADY_STARTED
) {
165 DEBUG ((EFI_D_INFO
, "Support(): Already Started. on handle %p\n", Controller
));
170 DEBUG ((EFI_D_INFO
, "Support(): UNDI3.1 found on handle %p\n", Controller
));
173 // check the version, we don't want to connect to the undi16
175 if (NiiProtocol
->Type
!= EfiNetworkInterfaceUndi
) {
176 Status
= EFI_UNSUPPORTED
;
180 // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.
182 if ((NiiProtocol
->Id
& 0x0F) != 0) {
183 DEBUG ((EFI_D_NET
, "\n!PXE structure is not paragraph aligned.\n"));
184 Status
= EFI_UNSUPPORTED
;
188 Pxe
= (PXE_UNDI
*) (UINTN
) (NiiProtocol
->Id
);
191 // Verify !PXE revisions.
193 if (Pxe
->hw
.Signature
!= PXE_ROMID_SIGNATURE
) {
194 DEBUG ((EFI_D_NET
, "\n!PXE signature is not valid.\n"));
195 Status
= EFI_UNSUPPORTED
;
199 if (Pxe
->hw
.Rev
< PXE_ROMID_REV
) {
200 DEBUG ((EFI_D_NET
, "\n!PXE.Rev is not supported.\n"));
201 Status
= EFI_UNSUPPORTED
;
205 if (Pxe
->hw
.MajorVer
< PXE_ROMID_MAJORVER
) {
207 DEBUG ((EFI_D_NET
, "\n!PXE.MajorVer is not supported.\n"));
208 Status
= EFI_UNSUPPORTED
;
211 } else if (Pxe
->hw
.MajorVer
== PXE_ROMID_MAJORVER
&& Pxe
->hw
.MinorVer
< PXE_ROMID_MINORVER
) {
212 DEBUG ((EFI_D_NET
, "\n!PXE.MinorVer is not supported."));
213 Status
= EFI_UNSUPPORTED
;
217 // Do S/W UNDI specific checks.
219 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_HW_UNDI
) == 0) {
220 if (Pxe
->sw
.EntryPoint
< Pxe
->sw
.Len
) {
221 DEBUG ((EFI_D_NET
, "\n!PXE S/W entry point is not valid."));
222 Status
= EFI_UNSUPPORTED
;
226 if (Pxe
->sw
.BusCnt
== 0) {
227 DEBUG ((EFI_D_NET
, "\n!PXE.BusCnt is zero."));
228 Status
= EFI_UNSUPPORTED
;
233 Status
= EFI_SUCCESS
;
234 DEBUG ((EFI_D_INFO
, "Support(): supported on %p\n", Controller
));
239 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
240 This
->DriverBindingHandle
,
248 Start this driver on ControllerHandle. This service is called by the
249 EFI boot service ConnectController(). In order to make
250 drivers as small as possible, there are a few calling restrictions for
251 this service. ConnectController() must follow these
252 calling restrictions. If any other agent wishes to call Start() it
253 must also follow these calling restrictions.
255 @param This Protocol instance pointer.
256 @param ControllerHandle Handle of device to bind driver to.
257 @param RemainingDevicePath Optional parameter use to pick a specific child
260 @retval EFI_SUCCESS This driver is added to ControllerHandle
261 @retval EFI_DEVICE_ERROR This driver could not be started due to a device error
262 @retval other This driver does not support this device
267 SimpleNetworkDriverStart (
268 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
269 IN EFI_HANDLE Controller
,
270 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
273 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL
*Nii
;
274 EFI_DEVICE_PATH_PROTOCOL
*NiiDevicePath
;
280 PXE_PCI_CONFIG_INFO ConfigInfo
;
281 PCI_TYPE00
*ConfigHeader
;
284 PXE_STATFLAGS InitStatFlags
;
286 DEBUG ((EFI_D_NET
, "\nSnpNotifyNetworkInterfaceIdentifier() "));
288 Status
= gBS
->OpenProtocol (
290 &gEfiDevicePathProtocolGuid
,
291 (VOID
**) &NiiDevicePath
,
292 This
->DriverBindingHandle
,
294 EFI_OPEN_PROTOCOL_BY_DRIVER
297 if (EFI_ERROR (Status
)) {
301 Status
= gBS
->LocateDevicePath (
302 &gEfiPciIoProtocolGuid
,
307 if (EFI_ERROR (Status
)) {
311 Status
= gBS
->OpenProtocol (
313 &gEfiPciIoProtocolGuid
,
315 This
->DriverBindingHandle
,
317 EFI_OPEN_PROTOCOL_GET_PROTOCOL
319 if (EFI_ERROR (Status
)) {
323 // Get the NII interface.
325 Status
= gBS
->OpenProtocol (
327 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
329 This
->DriverBindingHandle
,
331 EFI_OPEN_PROTOCOL_BY_DRIVER
333 if (EFI_ERROR (Status
)) {
336 &gEfiDevicePathProtocolGuid
,
337 This
->DriverBindingHandle
,
343 DEBUG ((EFI_D_INFO
, "Start(): UNDI3.1 found\n"));
345 Pxe
= (PXE_UNDI
*) (UINTN
) (Nii
->Id
);
347 if (Calc8BitCksum (Pxe
, Pxe
->hw
.Len
) != 0) {
348 DEBUG ((EFI_D_NET
, "\n!PXE checksum is not correct.\n"));
352 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
) != 0) {
354 // We can get any packets.
356 } else if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
) != 0) {
358 // We need to be able to get broadcast packets for DHCP.
359 // If we do not have promiscuous support, we must at least have
360 // broadcast support or we cannot do DHCP!
363 DEBUG ((EFI_D_NET
, "\nUNDI does not have promiscuous or broadcast support."));
367 // OK, we like this UNDI, and we know snp is not already there on this handle
368 // Allocate and initialize a new simple network protocol structure.
370 Status
= mPciIo
->AllocateBuffer (
374 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
379 if (Status
!= EFI_SUCCESS
) {
380 DEBUG ((EFI_D_NET
, "\nCould not allocate SNP_DRIVER structure.\n"));
384 Snp
= (SNP_DRIVER
*) (UINTN
) Address
;
386 ZeroMem (Snp
, sizeof (SNP_DRIVER
));
389 Snp
->Signature
= SNP_DRIVER_SIGNATURE
;
391 EfiInitializeLock (&Snp
->Lock
, TPL_NOTIFY
);
393 Snp
->Snp
.Revision
= EFI_SIMPLE_NETWORK_PROTOCOL_REVISION
;
394 Snp
->Snp
.Start
= SnpUndi32Start
;
395 Snp
->Snp
.Stop
= SnpUndi32Stop
;
396 Snp
->Snp
.Initialize
= SnpUndi32Initialize
;
397 Snp
->Snp
.Reset
= SnpUndi32Reset
;
398 Snp
->Snp
.Shutdown
= SnpUndi32Shutdown
;
399 Snp
->Snp
.ReceiveFilters
= SnpUndi32ReceiveFilters
;
400 Snp
->Snp
.StationAddress
= SnpUndi32StationAddress
;
401 Snp
->Snp
.Statistics
= SnpUndi32Statistics
;
402 Snp
->Snp
.MCastIpToMac
= SnpUndi32McastIpToMac
;
403 Snp
->Snp
.NvData
= SnpUndi32NvData
;
404 Snp
->Snp
.GetStatus
= SnpUndi32GetStatus
;
405 Snp
->Snp
.Transmit
= SnpUndi32Transmit
;
406 Snp
->Snp
.Receive
= SnpUndi32Receive
;
407 Snp
->Snp
.WaitForPacket
= NULL
;
409 Snp
->Snp
.Mode
= &Snp
->Mode
;
411 Snp
->TxRxBufferSize
= 0;
412 Snp
->TxRxBuffer
= NULL
;
414 Snp
->IfNum
= Nii
->IfNum
;
416 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_HW_UNDI
) != 0) {
417 Snp
->IsSwUndi
= FALSE
;
418 Snp
->IssueUndi32Command
= &IssueHwUndiCommand
;
420 Snp
->IsSwUndi
= TRUE
;
422 if ((Pxe
->sw
.Implementation
& PXE_ROMID_IMP_SW_VIRT_ADDR
) != 0) {
423 Snp
->IssueUndi32Command
= (ISSUE_UNDI32_COMMAND
) (UINTN
) Pxe
->sw
.EntryPoint
;
425 Snp
->IssueUndi32Command
= (ISSUE_UNDI32_COMMAND
) (UINTN
) ((UINT8
) (UINTN
) Pxe
+ Pxe
->sw
.EntryPoint
);
429 // Allocate a global CPB and DB buffer for this UNDI interface.
430 // we do this because:
432 // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be
433 // within 2GB limit, create them here and map them so that when undi calls
434 // v2p callback to check if the physical address is < 2gb, we will pass.
436 // -This is not a requirement for 3.1 or later UNDIs but the code looks
437 // simpler if we use the same cpb, db variables for both old and new undi
438 // interfaces from all the SNP interface calls (we don't map the buffers
439 // for the newer undi interfaces though)
441 // -it is OK to allocate one global set of CPB, DB pair for each UNDI
442 // interface as EFI does not multi-task and so SNP will not be re-entered!
444 Status
= mPciIo
->AllocateBuffer (
448 SNP_MEM_PAGES (4096),
453 if (Status
!= EFI_SUCCESS
) {
454 DEBUG ((EFI_D_NET
, "\nCould not allocate CPB and DB structures.\n"));
455 goto Error_DeleteSNP
;
458 Snp
->Cpb
= (VOID
*) (UINTN
) Address
;
459 Snp
->Db
= (VOID
*) ((UINTN
) Address
+ 2048);
462 // PxeStart call is going to give the callback functions to UNDI, these callback
463 // functions use the BarIndex values from the snp structure, so these must be initialized
464 // with default values before doing a PxeStart. The correct values can be obtained after
465 // getting the config information from UNDI
467 Snp
->MemoryBarIndex
= 0;
471 // we need the undi init information many times in this snp code, just get it
472 // once here and store it in the snp driver structure. to get Init Info
473 // from UNDI we have to start undi first.
475 Status
= PxeStart (Snp
);
477 if (Status
!= EFI_SUCCESS
) {
478 goto Error_DeleteSNP
;
481 Snp
->Cdb
.OpCode
= PXE_OPCODE_GET_INIT_INFO
;
482 Snp
->Cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
484 Snp
->Cdb
.CPBsize
= PXE_CPBSIZE_NOT_USED
;
485 Snp
->Cdb
.CPBaddr
= PXE_DBADDR_NOT_USED
;
487 Snp
->Cdb
.DBsize
= (UINT16
) sizeof (Snp
->InitInfo
);
488 Snp
->Cdb
.DBaddr
= (UINT64
)(UINTN
) (&Snp
->InitInfo
);
490 Snp
->Cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
491 Snp
->Cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
493 Snp
->Cdb
.IFnum
= Snp
->IfNum
;
494 Snp
->Cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
496 DEBUG ((EFI_D_NET
, "\nSnp->undi.get_init_info() "));
498 (*Snp
->IssueUndi32Command
) ((UINT64
)(UINTN
) &Snp
->Cdb
);
501 // Save the INIT Stat Code...
503 InitStatFlags
= Snp
->Cdb
.StatFlags
;
505 if (Snp
->Cdb
.StatCode
!= PXE_STATCODE_SUCCESS
) {
506 DEBUG ((EFI_D_NET
, "\nSnp->undi.init_info() %xh:%xh\n", Snp
->Cdb
.StatFlags
, Snp
->Cdb
.StatCode
));
508 goto Error_DeleteSNP
;
511 Snp
->Cdb
.OpCode
= PXE_OPCODE_GET_CONFIG_INFO
;
512 Snp
->Cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
514 Snp
->Cdb
.CPBsize
= PXE_CPBSIZE_NOT_USED
;
515 Snp
->Cdb
.CPBaddr
= PXE_DBADDR_NOT_USED
;
517 Snp
->Cdb
.DBsize
= (UINT16
) sizeof (ConfigInfo
);
518 Snp
->Cdb
.DBaddr
= (UINT64
)(UINTN
) &ConfigInfo
;
520 Snp
->Cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
521 Snp
->Cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
523 Snp
->Cdb
.IFnum
= Snp
->IfNum
;
524 Snp
->Cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
526 DEBUG ((EFI_D_NET
, "\nSnp->undi.get_config_info() "));
528 (*Snp
->IssueUndi32Command
) ((UINT64
)(UINTN
) &Snp
->Cdb
);
530 if (Snp
->Cdb
.StatCode
!= PXE_STATCODE_SUCCESS
) {
531 DEBUG ((EFI_D_NET
, "\nSnp->undi.config_info() %xh:%xh\n", Snp
->Cdb
.StatFlags
, Snp
->Cdb
.StatCode
));
533 goto Error_DeleteSNP
;
536 // Find the correct BAR to do IO.
539 // Enumerate through the PCI BARs for the device to determine which one is
540 // the IO BAR. Save the index of the BAR into the adapter info structure.
541 // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped
543 ConfigHeader
= (PCI_TYPE00
*) &ConfigInfo
.Config
.Byte
[0];
544 TempBar
= (UINT32
*) &ConfigHeader
->Device
.Bar
[0];
545 for (BarIndex
= 0; BarIndex
<= 5; BarIndex
++) {
546 if ((*TempBar
& PCI_BAR_MEM_MASK
) == PCI_BAR_MEM_64BIT
) {
548 // This is a 64-bit memory bar, skip this and the
554 if ((*TempBar
& PCI_BAR_IO_MASK
) == PCI_BAR_IO_MODE
) {
555 Snp
->IoBarIndex
= BarIndex
;
563 // Initialize simple network protocol mode structure
565 Snp
->Mode
.State
= EfiSimpleNetworkStopped
;
566 Snp
->Mode
.HwAddressSize
= Snp
->InitInfo
.HWaddrLen
;
567 Snp
->Mode
.MediaHeaderSize
= Snp
->InitInfo
.MediaHeaderLen
;
568 Snp
->Mode
.MaxPacketSize
= Snp
->InitInfo
.FrameDataLen
;
569 Snp
->Mode
.NvRamAccessSize
= Snp
->InitInfo
.NvWidth
;
570 Snp
->Mode
.NvRamSize
= Snp
->InitInfo
.NvCount
* Snp
->Mode
.NvRamAccessSize
;
571 Snp
->Mode
.IfType
= Snp
->InitInfo
.IFtype
;
572 Snp
->Mode
.MaxMCastFilterCount
= Snp
->InitInfo
.MCastFilterCnt
;
573 Snp
->Mode
.MCastFilterCount
= 0;
575 switch (InitStatFlags
& PXE_STATFLAGS_CABLE_DETECT_MASK
) {
576 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED
:
577 Snp
->Mode
.MediaPresentSupported
= TRUE
;
580 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED
:
582 Snp
->Mode
.MediaPresentSupported
= FALSE
;
585 switch (InitStatFlags
& PXE_STATFLAGS_GET_STATUS_NO_MEDIA_MASK
) {
586 case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED
:
587 Snp
->MediaStatusSupported
= TRUE
;
590 case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_NOT_SUPPORTED
:
592 Snp
->MediaStatusSupported
= FALSE
;
595 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_STATION_ADDR_SETTABLE
) != 0) {
596 Snp
->Mode
.MacAddressChangeable
= TRUE
;
598 Snp
->Mode
.MacAddressChangeable
= FALSE
;
601 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED
) != 0) {
602 Snp
->Mode
.MultipleTxSupported
= TRUE
;
604 Snp
->Mode
.MultipleTxSupported
= FALSE
;
607 Snp
->Mode
.ReceiveFilterMask
= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
609 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
) != 0) {
610 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
614 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
) != 0) {
615 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
619 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
) != 0) {
620 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
624 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED
) != 0) {
625 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
629 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
) != 0) {
630 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
634 Snp
->Mode
.ReceiveFilterSetting
= 0;
637 // need to get the station address to save in the mode structure. we need to
638 // initialize the UNDI first for this.
640 Snp
->TxRxBufferSize
= Snp
->InitInfo
.MemoryRequired
;
641 Status
= PxeInit (Snp
, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE
);
643 if (EFI_ERROR (Status
)) {
645 goto Error_DeleteSNP
;
648 Status
= PxeGetStnAddr (Snp
);
650 if (Status
!= EFI_SUCCESS
) {
651 DEBUG ((EFI_D_ERROR
, "\nSnp->undi.get_station_addr() failed.\n"));
654 goto Error_DeleteSNP
;
657 Snp
->Mode
.MediaPresent
= FALSE
;
660 // We should not leave UNDI started and initialized here. this DriverStart()
661 // routine must only find and attach the SNP interface to UNDI layer that it
662 // finds on the given handle!
663 // The UNDI layer will be started when upper layers call Snp->start.
664 // How ever, this DriverStart() must fill up the snp mode structure which
665 // contains the MAC address of the NIC. For this reason we started and
666 // initialized UNDI here, now we are done, do a shutdown and stop of the
673 // Create EXIT_BOOT_SERIVES Event
675 Status
= gBS
->CreateEventEx (
678 SnpNotifyExitBootServices
,
680 &gEfiEventExitBootServicesGuid
,
681 &Snp
->ExitBootServicesEvent
683 if (EFI_ERROR (Status
)) {
684 goto Error_DeleteSNP
;
688 // add SNP to the undi handle
690 Status
= gBS
->InstallProtocolInterface (
692 &gEfiSimpleNetworkProtocolGuid
,
693 EFI_NATIVE_INTERFACE
,
697 if (!EFI_ERROR (Status
)) {
703 SNP_MEM_PAGES (4096),
711 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
717 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
718 This
->DriverBindingHandle
,
724 &gEfiDevicePathProtocolGuid
,
725 This
->DriverBindingHandle
,
730 // If we got here that means we are in error state.
732 if (!EFI_ERROR (Status
)) {
733 Status
= EFI_DEVICE_ERROR
;
740 Stop this driver on ControllerHandle. This service is called by the
741 EFI boot service DisconnectController(). In order to
742 make drivers as small as possible, there are a few calling
743 restrictions for this service. DisconnectController()
744 must follow these calling restrictions. If any other agent wishes
745 to call Stop() it must also follow these calling restrictions.
747 @param This Protocol instance pointer.
748 @param ControllerHandle Handle of device to stop driver on
749 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
750 children is zero stop the entire bus driver.
751 @param ChildHandleBuffer List of Child Handles to Stop.
753 @retval EFI_SUCCESS This driver is removed ControllerHandle
754 @retval other This driver was not removed from this device
759 SimpleNetworkDriverStop (
760 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
761 IN EFI_HANDLE Controller
,
762 IN UINTN NumberOfChildren
,
763 IN EFI_HANDLE
*ChildHandleBuffer
767 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpProtocol
;
771 // Get our context back.
773 Status
= gBS
->OpenProtocol (
775 &gEfiSimpleNetworkProtocolGuid
,
776 (VOID
**) &SnpProtocol
,
777 This
->DriverBindingHandle
,
779 EFI_OPEN_PROTOCOL_GET_PROTOCOL
782 if (EFI_ERROR (Status
)) {
783 return EFI_UNSUPPORTED
;
786 Snp
= EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol
);
788 Status
= gBS
->UninstallProtocolInterface (
790 &gEfiSimpleNetworkProtocolGuid
,
794 if (EFI_ERROR (Status
)) {
799 // Close EXIT_BOOT_SERIVES Event
801 gBS
->CloseEvent (Snp
->ExitBootServicesEvent
);
803 Status
= gBS
->CloseProtocol (
805 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
806 This
->DriverBindingHandle
,
810 Status
= gBS
->CloseProtocol (
812 &gEfiDevicePathProtocolGuid
,
813 This
->DriverBindingHandle
,
822 SNP_MEM_PAGES (4096),
828 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
836 // Simple Network Protocol Driver Global Variables
838 EFI_DRIVER_BINDING_PROTOCOL gSimpleNetworkDriverBinding
= {
839 SimpleNetworkDriverSupported
,
840 SimpleNetworkDriverStart
,
841 SimpleNetworkDriverStop
,
849 This routine maps the given CPU address to a Device address. It creates a
850 an entry in the map list with the virtual and physical addresses and the
853 @param V2p pointer to return a map list node pointer.
854 @param Type the direction in which the data flows from the given
855 virtual address device->cpu or cpu->device or both
857 @param VirtualAddress virtual address (or CPU address) to be mapped.
858 @param BufferSize size of the buffer to be mapped.
860 @retval EFI_SUCEESS routine has completed the mapping.
861 @retval EFI_INVALID_PARAMETER invalid parameter.
862 @retval EFI_OUT_OF_RESOURCES out of resource.
863 @retval other error as indicated.
869 EFI_PCI_IO_PROTOCOL_OPERATION Type
,
870 VOID
*VirtualAddress
,
876 if ((V2p
== NULL
) || (VirtualAddress
== NULL
) || (BufferSize
== 0)) {
877 return EFI_INVALID_PARAMETER
;
880 *V2p
= AllocatePool (sizeof (V2P
));
882 return EFI_OUT_OF_RESOURCES
;
885 Status
= mPciIo
->Map (
890 &(*V2p
)->PhysicalAddress
,
893 if (Status
!= EFI_SUCCESS
) {
897 (*V2p
)->VirtualAddress
= VirtualAddress
;
898 (*V2p
)->BufferSize
= BufferSize
;
907 This routine searches the linked list of mapped address nodes (for undi3.0
908 interface) to find the node that corresponds to the given virtual address and
909 returns a pointer to that node.
911 @param V2p pointer to return a map list node pointer.
912 @param VirtualAddr virtual address (or CPU address) to be searched in
915 @retval EFI_SUCEESS A match was found.
916 @retval Other A match cannot be found.
927 if (V2p
== NULL
|| VirtualAddr
== NULL
) {
928 return EFI_INVALID_PARAMETER
;
931 for (Ptr
= mV2p
; Ptr
!= NULL
; Ptr
= Ptr
->Next
) {
932 if (Ptr
->VirtualAddress
== VirtualAddr
) {
938 return EFI_NOT_FOUND
;
943 Unmap the given virtual address and free the memory allocated for the map list
944 node corresponding to that address.
946 @param VirtualAddress virtual address (or CPU address) to be unmapped.
948 @retval EFI_SUCEESS Successfully unmapped.
949 @retval Other Other errors as indicated.
961 if (VirtualAddress
== NULL
) {
962 return EFI_INVALID_PARAMETER
;
966 return EFI_NOT_FOUND
;
969 // Is our node at the head of the list??
971 if ((Current
= mV2p
)->VirtualAddress
== VirtualAddress
) {
974 Status
= mPciIo
->Unmap (mPciIo
, Current
->Unmap
);
978 if (EFI_ERROR (Status
)) {
979 DEBUG ((EFI_D_ERROR
, "Unmap failed with status = %r\n", Status
));
984 for (; Current
->Next
!= NULL
; Current
= Next
) {
985 if ((Next
= Current
->Next
)->VirtualAddress
== VirtualAddress
) {
986 Current
->Next
= Next
->Next
;
987 Status
= mPciIo
->Unmap (mPciIo
, Next
->Unmap
);
990 if (EFI_ERROR (Status
)) {
991 DEBUG ((EFI_D_ERROR
, "Unmap failed with status = %r\n", Status
));
997 return EFI_NOT_FOUND
;
1001 The SNP driver entry point.
1003 @param ImageHandle The driver image handle.
1004 @param SystemTable The system table.
1006 @retval EFI_SUCEESS Initialization routine has found UNDI hardware,
1007 loaded it's ROM, and installed a notify event for
1008 the Network Indentifier Interface Protocol
1010 @retval Other Return value from HandleProtocol for
1011 DeviceIoProtocol or LoadedImageProtocol
1016 InitializeSnpNiiDriver (
1017 IN EFI_HANDLE ImageHandle
,
1018 IN EFI_SYSTEM_TABLE
*SystemTable
1021 return EfiLibInstallDriverBindingComponentName2 (
1024 &gSimpleNetworkDriverBinding
,
1026 &gSimpleNetworkComponentName
,
1027 &gSimpleNetworkComponentName2