2 Implementation of driver entry point and driver binding protocol.
4 Copyright (c) 2004 - 2010, 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
65 DEBUG ((EFI_D_ERROR
, "\nIssueHwUndiCommand() - This should not be called!"));
68 return EFI_INVALID_PARAMETER
;
72 // %%TBD - For now, nothing is done.
74 return EFI_UNSUPPORTED
;
79 Compute 8-bit checksum of a buffer.
81 @param Buffer Pointer to buffer.
82 @param Length Length of buffer in bytes.
84 @return 8-bit checksum of all bytes in buffer, or zero if ptr is NULL or len
100 if (Ptr
== NULL
|| Length
== 0) {
104 while (Length
-- != 0) {
105 Cksum
= (UINT8
) (Cksum
+ *Ptr
++);
112 Test to see if this driver supports ControllerHandle. This service
113 is called by the EFI boot service ConnectController(). In
114 order to make drivers as small as possible, there are a few calling
115 restrictions for this service. ConnectController() must
116 follow these calling restrictions. If any other agent wishes to call
117 Supported() it must also follow these calling restrictions.
119 @param This Protocol instance pointer.
120 @param ControllerHandle Handle of device to test.
121 @param RemainingDevicePath Optional parameter use to pick a specific child
124 @retval EFI_SUCCESS This driver supports this device.
125 @retval EFI_ALREADY_STARTED This driver is already running on this device.
126 @retval other This driver does not support this device.
131 SimpleNetworkDriverSupported (
132 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
133 IN EFI_HANDLE Controller
,
134 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
138 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL
*NiiProtocol
;
141 Status
= gBS
->OpenProtocol (
143 &gEfiDevicePathProtocolGuid
,
145 This
->DriverBindingHandle
,
147 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
149 if (EFI_ERROR (Status
)) {
153 Status
= gBS
->OpenProtocol (
155 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
156 (VOID
**) &NiiProtocol
,
157 This
->DriverBindingHandle
,
159 EFI_OPEN_PROTOCOL_BY_DRIVER
162 if (EFI_ERROR (Status
)) {
163 if (Status
== EFI_ALREADY_STARTED
) {
164 DEBUG ((EFI_D_INFO
, "Support(): Already Started. on handle %p\n", Controller
));
169 DEBUG ((EFI_D_INFO
, "Support(): UNDI3.1 found on handle %p\n", Controller
));
172 // check the version, we don't want to connect to the undi16
174 if (NiiProtocol
->Type
!= EfiNetworkInterfaceUndi
) {
175 Status
= EFI_UNSUPPORTED
;
179 // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.
181 if ((NiiProtocol
->Id
& 0x0F) != 0) {
182 DEBUG ((EFI_D_NET
, "\n!PXE structure is not paragraph aligned.\n"));
183 Status
= EFI_UNSUPPORTED
;
187 Pxe
= (PXE_UNDI
*) (UINTN
) (NiiProtocol
->Id
);
190 // Verify !PXE revisions.
192 if (Pxe
->hw
.Signature
!= PXE_ROMID_SIGNATURE
) {
193 DEBUG ((EFI_D_NET
, "\n!PXE signature is not valid.\n"));
194 Status
= EFI_UNSUPPORTED
;
198 if (Pxe
->hw
.Rev
< PXE_ROMID_REV
) {
199 DEBUG ((EFI_D_NET
, "\n!PXE.Rev is not supported.\n"));
200 Status
= EFI_UNSUPPORTED
;
204 if (Pxe
->hw
.MajorVer
< PXE_ROMID_MAJORVER
) {
206 DEBUG ((EFI_D_NET
, "\n!PXE.MajorVer is not supported.\n"));
207 Status
= EFI_UNSUPPORTED
;
210 } else if (Pxe
->hw
.MajorVer
== PXE_ROMID_MAJORVER
&& Pxe
->hw
.MinorVer
< PXE_ROMID_MINORVER
) {
211 DEBUG ((EFI_D_NET
, "\n!PXE.MinorVer is not supported."));
212 Status
= EFI_UNSUPPORTED
;
216 // Do S/W UNDI specific checks.
218 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_HW_UNDI
) == 0) {
219 if (Pxe
->sw
.EntryPoint
< Pxe
->sw
.Len
) {
220 DEBUG ((EFI_D_NET
, "\n!PXE S/W entry point is not valid."));
221 Status
= EFI_UNSUPPORTED
;
225 if (Pxe
->sw
.BusCnt
== 0) {
226 DEBUG ((EFI_D_NET
, "\n!PXE.BusCnt is zero."));
227 Status
= EFI_UNSUPPORTED
;
232 Status
= EFI_SUCCESS
;
233 DEBUG ((EFI_D_INFO
, "Support(): supported on %p\n", Controller
));
238 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
239 This
->DriverBindingHandle
,
247 Start this driver on ControllerHandle. This service is called by the
248 EFI boot service ConnectController(). In order to make
249 drivers as small as possible, there are a few calling restrictions for
250 this service. ConnectController() must follow these
251 calling restrictions. If any other agent wishes to call Start() it
252 must also follow these calling restrictions.
254 @param This Protocol instance pointer.
255 @param ControllerHandle Handle of device to bind driver to.
256 @param RemainingDevicePath Optional parameter use to pick a specific child
259 @retval EFI_SUCCESS This driver is added to ControllerHandle
260 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
261 @retval other This driver does not support this device
266 SimpleNetworkDriverStart (
267 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
268 IN EFI_HANDLE Controller
,
269 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
272 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL
*Nii
;
273 EFI_DEVICE_PATH_PROTOCOL
*NiiDevicePath
;
279 PXE_PCI_CONFIG_INFO ConfigInfo
;
280 PCI_TYPE00
*ConfigHeader
;
283 PXE_STATFLAGS InitStatFlags
;
285 DEBUG ((EFI_D_NET
, "\nSnpNotifyNetworkInterfaceIdentifier() "));
287 Status
= gBS
->OpenProtocol (
289 &gEfiDevicePathProtocolGuid
,
290 (VOID
**) &NiiDevicePath
,
291 This
->DriverBindingHandle
,
293 EFI_OPEN_PROTOCOL_BY_DRIVER
296 if (EFI_ERROR (Status
)) {
300 Status
= gBS
->LocateDevicePath (
301 &gEfiPciIoProtocolGuid
,
306 if (EFI_ERROR (Status
)) {
310 Status
= gBS
->OpenProtocol (
312 &gEfiPciIoProtocolGuid
,
314 This
->DriverBindingHandle
,
316 EFI_OPEN_PROTOCOL_GET_PROTOCOL
318 if (EFI_ERROR (Status
)) {
322 // Get the NII interface.
324 Status
= gBS
->OpenProtocol (
326 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
328 This
->DriverBindingHandle
,
330 EFI_OPEN_PROTOCOL_BY_DRIVER
332 if (EFI_ERROR (Status
)) {
335 &gEfiDevicePathProtocolGuid
,
336 This
->DriverBindingHandle
,
342 DEBUG ((EFI_D_INFO
, "Start(): UNDI3.1 found\n"));
344 Pxe
= (PXE_UNDI
*) (UINTN
) (Nii
->Id
);
346 if (Calc8BitCksum (Pxe
, Pxe
->hw
.Len
) != 0) {
347 DEBUG ((EFI_D_NET
, "\n!PXE checksum is not correct.\n"));
351 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
) != 0) {
353 // We can get any packets.
355 } else if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
) != 0) {
357 // We need to be able to get broadcast packets for DHCP.
358 // If we do not have promiscuous support, we must at least have
359 // broadcast support or we cannot do DHCP!
362 DEBUG ((EFI_D_NET
, "\nUNDI does not have promiscuous or broadcast support."));
366 // OK, we like this UNDI, and we know snp is not already there on this handle
367 // Allocate and initialize a new simple network protocol structure.
369 Status
= mPciIo
->AllocateBuffer (
373 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
378 if (Status
!= EFI_SUCCESS
) {
379 DEBUG ((EFI_D_NET
, "\nCould not allocate SNP_DRIVER structure.\n"));
383 Snp
= (SNP_DRIVER
*) (UINTN
) Address
;
385 ZeroMem (Snp
, sizeof (SNP_DRIVER
));
388 Snp
->Signature
= SNP_DRIVER_SIGNATURE
;
390 EfiInitializeLock (&Snp
->Lock
, TPL_NOTIFY
);
392 Snp
->Snp
.Revision
= EFI_SIMPLE_NETWORK_PROTOCOL_REVISION
;
393 Snp
->Snp
.Start
= SnpUndi32Start
;
394 Snp
->Snp
.Stop
= SnpUndi32Stop
;
395 Snp
->Snp
.Initialize
= SnpUndi32Initialize
;
396 Snp
->Snp
.Reset
= SnpUndi32Reset
;
397 Snp
->Snp
.Shutdown
= SnpUndi32Shutdown
;
398 Snp
->Snp
.ReceiveFilters
= SnpUndi32ReceiveFilters
;
399 Snp
->Snp
.StationAddress
= SnpUndi32StationAddress
;
400 Snp
->Snp
.Statistics
= SnpUndi32Statistics
;
401 Snp
->Snp
.MCastIpToMac
= SnpUndi32McastIpToMac
;
402 Snp
->Snp
.NvData
= SnpUndi32NvData
;
403 Snp
->Snp
.GetStatus
= SnpUndi32GetStatus
;
404 Snp
->Snp
.Transmit
= SnpUndi32Transmit
;
405 Snp
->Snp
.Receive
= SnpUndi32Receive
;
406 Snp
->Snp
.WaitForPacket
= NULL
;
408 Snp
->Snp
.Mode
= &Snp
->Mode
;
410 Snp
->TxRxBufferSize
= 0;
411 Snp
->TxRxBuffer
= NULL
;
413 Snp
->IfNum
= Nii
->IfNum
;
415 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_HW_UNDI
) != 0) {
416 Snp
->IsSwUndi
= FALSE
;
417 Snp
->IssueUndi32Command
= &IssueHwUndiCommand
;
419 Snp
->IsSwUndi
= TRUE
;
421 if ((Pxe
->sw
.Implementation
& PXE_ROMID_IMP_SW_VIRT_ADDR
) != 0) {
422 Snp
->IssueUndi32Command
= (ISSUE_UNDI32_COMMAND
) (UINTN
) Pxe
->sw
.EntryPoint
;
424 Snp
->IssueUndi32Command
= (ISSUE_UNDI32_COMMAND
) (UINTN
) ((UINT8
) (UINTN
) Pxe
+ Pxe
->sw
.EntryPoint
);
428 // Allocate a global CPB and DB buffer for this UNDI interface.
429 // we do this because:
431 // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be
432 // within 2GB limit, create them here and map them so that when undi calls
433 // v2p callback to check if the physical address is < 2gb, we will pass.
435 // -This is not a requirement for 3.1 or later UNDIs but the code looks
436 // simpler if we use the same cpb, db variables for both old and new undi
437 // interfaces from all the SNP interface calls (we don't map the buffers
438 // for the newer undi interfaces though)
440 // -it is OK to allocate one global set of CPB, DB pair for each UNDI
441 // interface as EFI does not multi-task and so SNP will not be re-entered!
443 Status
= mPciIo
->AllocateBuffer (
447 SNP_MEM_PAGES (4096),
452 if (Status
!= EFI_SUCCESS
) {
453 DEBUG ((EFI_D_NET
, "\nCould not allocate CPB and DB structures.\n"));
454 goto Error_DeleteSNP
;
457 Snp
->Cpb
= (VOID
*) (UINTN
) Address
;
458 Snp
->Db
= (VOID
*) ((UINTN
) Address
+ 2048);
461 // PxeStart call is going to give the callback functions to UNDI, these callback
462 // functions use the BarIndex values from the snp structure, so these must be initialized
463 // with default values before doing a PxeStart. The correct values can be obtained after
464 // getting the config information from UNDI
466 Snp
->MemoryBarIndex
= 0;
470 // we need the undi init information many times in this snp code, just get it
471 // once here and store it in the snp driver structure. to get Init Info
472 // from UNDI we have to start undi first.
474 Status
= PxeStart (Snp
);
476 if (Status
!= EFI_SUCCESS
) {
477 goto Error_DeleteSNP
;
480 Snp
->Cdb
.OpCode
= PXE_OPCODE_GET_INIT_INFO
;
481 Snp
->Cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
483 Snp
->Cdb
.CPBsize
= PXE_CPBSIZE_NOT_USED
;
484 Snp
->Cdb
.CPBaddr
= PXE_DBADDR_NOT_USED
;
486 Snp
->Cdb
.DBsize
= (UINT16
) sizeof (Snp
->InitInfo
);
487 Snp
->Cdb
.DBaddr
= (UINT64
)(UINTN
) (&Snp
->InitInfo
);
489 Snp
->Cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
490 Snp
->Cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
492 Snp
->Cdb
.IFnum
= Snp
->IfNum
;
493 Snp
->Cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
495 DEBUG ((EFI_D_NET
, "\nSnp->undi.get_init_info() "));
497 (*Snp
->IssueUndi32Command
) ((UINT64
)(UINTN
) &Snp
->Cdb
);
500 // Save the INIT Stat Code...
502 InitStatFlags
= Snp
->Cdb
.StatFlags
;
504 if (Snp
->Cdb
.StatCode
!= PXE_STATCODE_SUCCESS
) {
505 DEBUG ((EFI_D_NET
, "\nSnp->undi.init_info() %xh:%xh\n", Snp
->Cdb
.StatFlags
, Snp
->Cdb
.StatCode
));
507 goto Error_DeleteSNP
;
510 Snp
->Cdb
.OpCode
= PXE_OPCODE_GET_CONFIG_INFO
;
511 Snp
->Cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
513 Snp
->Cdb
.CPBsize
= PXE_CPBSIZE_NOT_USED
;
514 Snp
->Cdb
.CPBaddr
= PXE_DBADDR_NOT_USED
;
516 Snp
->Cdb
.DBsize
= (UINT16
) sizeof (ConfigInfo
);
517 Snp
->Cdb
.DBaddr
= (UINT64
)(UINTN
) &ConfigInfo
;
519 Snp
->Cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
520 Snp
->Cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
522 Snp
->Cdb
.IFnum
= Snp
->IfNum
;
523 Snp
->Cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
525 DEBUG ((EFI_D_NET
, "\nSnp->undi.get_config_info() "));
527 (*Snp
->IssueUndi32Command
) ((UINT64
)(UINTN
) &Snp
->Cdb
);
529 if (Snp
->Cdb
.StatCode
!= PXE_STATCODE_SUCCESS
) {
530 DEBUG ((EFI_D_NET
, "\nSnp->undi.config_info() %xh:%xh\n", Snp
->Cdb
.StatFlags
, Snp
->Cdb
.StatCode
));
532 goto Error_DeleteSNP
;
535 // Find the correct BAR to do IO.
538 // Enumerate through the PCI BARs for the device to determine which one is
539 // the IO BAR. Save the index of the BAR into the adapter info structure.
540 // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped
542 ConfigHeader
= (PCI_TYPE00
*) &ConfigInfo
.Config
.Byte
[0];
543 TempBar
= (UINT32
*) &ConfigHeader
->Device
.Bar
[0];
544 for (BarIndex
= 0; BarIndex
<= 5; BarIndex
++) {
545 if ((*TempBar
& PCI_BAR_MEM_MASK
) == PCI_BAR_MEM_64BIT
) {
547 // This is a 64-bit memory bar, skip this and the
553 if ((*TempBar
& PCI_BAR_IO_MASK
) == PCI_BAR_IO_MODE
) {
554 Snp
->IoBarIndex
= BarIndex
;
562 // Initialize simple network protocol mode structure
564 Snp
->Mode
.State
= EfiSimpleNetworkStopped
;
565 Snp
->Mode
.HwAddressSize
= Snp
->InitInfo
.HWaddrLen
;
566 Snp
->Mode
.MediaHeaderSize
= Snp
->InitInfo
.MediaHeaderLen
;
567 Snp
->Mode
.MaxPacketSize
= Snp
->InitInfo
.FrameDataLen
;
568 Snp
->Mode
.NvRamAccessSize
= Snp
->InitInfo
.NvWidth
;
569 Snp
->Mode
.NvRamSize
= Snp
->InitInfo
.NvCount
* Snp
->Mode
.NvRamAccessSize
;
570 Snp
->Mode
.IfType
= Snp
->InitInfo
.IFtype
;
571 Snp
->Mode
.MaxMCastFilterCount
= Snp
->InitInfo
.MCastFilterCnt
;
572 Snp
->Mode
.MCastFilterCount
= 0;
574 switch (InitStatFlags
& PXE_STATFLAGS_CABLE_DETECT_MASK
) {
575 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED
:
576 Snp
->Mode
.MediaPresentSupported
= TRUE
;
579 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED
:
581 Snp
->Mode
.MediaPresentSupported
= FALSE
;
584 switch (InitStatFlags
& PXE_STATFLAGS_GET_STATUS_NO_MEDIA_MASK
) {
585 case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED
:
586 Snp
->MediaStatusSupported
= TRUE
;
589 case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_NOT_SUPPORTED
:
591 Snp
->MediaStatusSupported
= FALSE
;
594 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_STATION_ADDR_SETTABLE
) != 0) {
595 Snp
->Mode
.MacAddressChangeable
= TRUE
;
597 Snp
->Mode
.MacAddressChangeable
= FALSE
;
600 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED
) != 0) {
601 Snp
->Mode
.MultipleTxSupported
= TRUE
;
603 Snp
->Mode
.MultipleTxSupported
= FALSE
;
606 Snp
->Mode
.ReceiveFilterMask
= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
608 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
) != 0) {
609 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
613 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
) != 0) {
614 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
618 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
) != 0) {
619 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
623 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED
) != 0) {
624 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
628 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
) != 0) {
629 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
633 Snp
->Mode
.ReceiveFilterSetting
= 0;
636 // need to get the station address to save in the mode structure. we need to
637 // initialize the UNDI first for this.
639 Snp
->TxRxBufferSize
= Snp
->InitInfo
.MemoryRequired
;
640 Status
= PxeInit (Snp
, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE
);
642 if (EFI_ERROR (Status
)) {
644 goto Error_DeleteSNP
;
647 Status
= PxeGetStnAddr (Snp
);
649 if (Status
!= EFI_SUCCESS
) {
650 DEBUG ((EFI_D_ERROR
, "\nSnp->undi.get_station_addr() failed.\n"));
653 goto Error_DeleteSNP
;
656 Snp
->Mode
.MediaPresent
= FALSE
;
659 // We should not leave UNDI started and initialized here. this DriverStart()
660 // routine must only find and attach the SNP interface to UNDI layer that it
661 // finds on the given handle!
662 // The UNDI layer will be started when upper layers call Snp->start.
663 // How ever, this DriverStart() must fill up the snp mode structure which
664 // contains the MAC address of the NIC. For this reason we started and
665 // initialized UNDI here, now we are done, do a shutdown and stop of the
672 // Create EXIT_BOOT_SERIVES Event
674 Status
= gBS
->CreateEventEx (
677 SnpNotifyExitBootServices
,
679 &gEfiEventExitBootServicesGuid
,
680 &Snp
->ExitBootServicesEvent
682 if (EFI_ERROR (Status
)) {
683 goto Error_DeleteSNP
;
687 // add SNP to the undi handle
689 Status
= gBS
->InstallProtocolInterface (
691 &gEfiSimpleNetworkProtocolGuid
,
692 EFI_NATIVE_INTERFACE
,
696 if (!EFI_ERROR (Status
)) {
700 Status
= mPciIo
->FreeBuffer (
702 SNP_MEM_PAGES (4096),
710 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
716 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
717 This
->DriverBindingHandle
,
723 &gEfiDevicePathProtocolGuid
,
724 This
->DriverBindingHandle
,
732 Stop this driver on ControllerHandle. This service is called by the
733 EFI boot service DisconnectController(). In order to
734 make drivers as small as possible, there are a few calling
735 restrictions for this service. DisconnectController()
736 must follow these calling restrictions. If any other agent wishes
737 to call Stop() it must also follow these calling restrictions.
739 @param This Protocol instance pointer.
740 @param ControllerHandle Handle of device to stop driver on
741 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
742 children is zero stop the entire bus driver.
743 @param ChildHandleBuffer List of Child Handles to Stop.
745 @retval EFI_SUCCESS This driver is removed ControllerHandle
746 @retval other This driver was not removed from this device
751 SimpleNetworkDriverStop (
752 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
753 IN EFI_HANDLE Controller
,
754 IN UINTN NumberOfChildren
,
755 IN EFI_HANDLE
*ChildHandleBuffer
759 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpProtocol
;
763 // Get our context back.
765 Status
= gBS
->OpenProtocol (
767 &gEfiSimpleNetworkProtocolGuid
,
768 (VOID
**) &SnpProtocol
,
769 This
->DriverBindingHandle
,
771 EFI_OPEN_PROTOCOL_GET_PROTOCOL
774 if (EFI_ERROR (Status
)) {
775 return EFI_UNSUPPORTED
;
778 Snp
= EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol
);
780 Status
= gBS
->UninstallProtocolInterface (
782 &gEfiSimpleNetworkProtocolGuid
,
786 if (EFI_ERROR (Status
)) {
791 // Close EXIT_BOOT_SERIVES Event
793 gBS
->CloseEvent (Snp
->ExitBootServicesEvent
);
795 Status
= gBS
->CloseProtocol (
797 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
798 This
->DriverBindingHandle
,
802 Status
= gBS
->CloseProtocol (
804 &gEfiDevicePathProtocolGuid
,
805 This
->DriverBindingHandle
,
814 SNP_MEM_PAGES (4096),
820 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
828 // Simple Network Protocol Driver Global Variables
830 EFI_DRIVER_BINDING_PROTOCOL mSimpleNetworkDriverBinding
= {
831 SimpleNetworkDriverSupported
,
832 SimpleNetworkDriverStart
,
833 SimpleNetworkDriverStop
,
841 This routine maps the given CPU address to a Device address. It creates a
842 an entry in the map list with the virtual and physical addresses and the
845 @param V2p pointer to return a map list node pointer.
846 @param Type the direction in which the data flows from the given
847 virtual address device->cpu or cpu->device or both
849 @param VirtualAddress virtual address (or CPU address) to be mapped.
850 @param BufferSize size of the buffer to be mapped.
852 @retval EFI_SUCEESS routine has completed the mapping.
853 @retval EFI_INVALID_PARAMETER invalid parameter.
854 @retval EFI_OUT_OF_RESOURCES out of resource.
855 @retval other error as indicated.
861 EFI_PCI_IO_PROTOCOL_OPERATION Type
,
862 VOID
*VirtualAddress
,
868 if ((V2p
== NULL
) || (VirtualAddress
== NULL
) || (BufferSize
== 0)) {
869 return EFI_INVALID_PARAMETER
;
872 *V2p
= AllocatePool (sizeof (V2P
));
874 return EFI_OUT_OF_RESOURCES
;
877 Status
= mPciIo
->Map (
882 &(*V2p
)->PhysicalAddress
,
885 if (Status
!= EFI_SUCCESS
) {
889 (*V2p
)->VirtualAddress
= VirtualAddress
;
890 (*V2p
)->BufferSize
= BufferSize
;
899 This routine searches the linked list of mapped address nodes (for undi3.0
900 interface) to find the node that corresponds to the given virtual address and
901 returns a pointer to that node.
903 @param V2p pointer to return a map list node pointer.
904 @param VirtualAddr virtual address (or CPU address) to be searched in
907 @retval EFI_SUCEESS A match was found.
908 @retval Other A match cannot be found.
919 if (V2p
== NULL
|| VirtualAddr
== NULL
) {
920 return EFI_INVALID_PARAMETER
;
923 for (Ptr
= mV2p
; Ptr
!= NULL
; Ptr
= Ptr
->Next
) {
924 if (Ptr
->VirtualAddress
== VirtualAddr
) {
930 return EFI_NOT_FOUND
;
935 Unmap the given virtual address and free the memory allocated for the map list
936 node corresponding to that address.
938 @param VirtualAddress virtual address (or CPU address) to be unmapped.
940 @retval EFI_SUCEESS Successfully unmapped.
941 @retval Other Other errors as indicated.
953 if (VirtualAddress
== NULL
) {
954 return EFI_INVALID_PARAMETER
;
958 return EFI_NOT_FOUND
;
961 // Is our node at the head of the list??
963 if ((Current
= mV2p
)->VirtualAddress
== VirtualAddress
) {
966 Status
= mPciIo
->Unmap (mPciIo
, Current
->Unmap
);
970 if (EFI_ERROR (Status
)) {
971 DEBUG ((EFI_D_ERROR
, "Unmap failed with status = %r\n", Status
));
976 for (; Current
->Next
!= NULL
; Current
= Next
) {
977 if ((Next
= Current
->Next
)->VirtualAddress
== VirtualAddress
) {
978 Current
->Next
= Next
->Next
;
979 Status
= mPciIo
->Unmap (mPciIo
, Next
->Unmap
);
982 if (EFI_ERROR (Status
)) {
983 DEBUG ((EFI_D_ERROR
, "Unmap failed with status = %r\n", Status
));
989 return EFI_NOT_FOUND
;
993 The SNP driver entry point.
995 @param ImageHandle The driver image handle.
996 @param SystemTable The system table.
998 @retval EFI_SUCEESS Initialization routine has found UNDI hardware,
999 loaded it's ROM, and installed a notify event for
1000 the Network Indentifier Interface Protocol
1002 @retval Other Return value from HandleProtocol for
1003 DeviceIoProtocol or LoadedImageProtocol
1008 InitializeSnpNiiDriver (
1009 IN EFI_HANDLE ImageHandle
,
1010 IN EFI_SYSTEM_TABLE
*SystemTable
1013 return EfiLibInstallDriverBindingComponentName2 (
1016 &mSimpleNetworkDriverBinding
,
1018 &gSimpleNetworkComponentName
,
1019 &gSimpleNetworkComponentName2