2 Implementation of driver entry point and driver binding protocol.
4 Copyright (c) 2004 - 2008, Intel Corporation. <BR>
5 All rights reserved. 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
27 Send command to UNDI. It does nothing currently.
29 @param Cdb command to be sent to UNDI.
31 @retval EFI_INVALID_PARAMETER The command is 0.
32 @retval EFI_UNSUPPORTED Default return status because it's not
41 DEBUG ((EFI_D_ERROR
, "\nIssueHwUndiCommand() - This should not be called!"));
44 return EFI_INVALID_PARAMETER
;
48 // %%TBD - For now, nothing is done.
50 return EFI_UNSUPPORTED
;
55 Compute 8-bit checksum of a buffer.
57 @param Buffer Pointer to buffer.
58 @param Length Length of buffer in bytes.
60 @return 8-bit checksum of all bytes in buffer, or zero if ptr is NULL or len
76 if (Ptr
== NULL
|| Length
== 0) {
80 while (Length
-- != 0) {
81 Cksum
= (UINT8
) (Cksum
+ *Ptr
++);
88 Test to see if this driver supports ControllerHandle. This service
89 is called by the EFI boot service ConnectController(). In
90 order to make drivers as small as possible, there are a few calling
91 restrictions for this service. ConnectController() must
92 follow these calling restrictions. If any other agent wishes to call
93 Supported() it must also follow these calling restrictions.
95 @param This Protocol instance pointer.
96 @param ControllerHandle Handle of device to test.
97 @param RemainingDevicePath Optional parameter use to pick a specific child
100 @retval EFI_SUCCESS This driver supports this device.
101 @retval EFI_ALREADY_STARTED This driver is already running on this device.
102 @retval other This driver does not support this device.
107 SimpleNetworkDriverSupported (
108 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
109 IN EFI_HANDLE Controller
,
110 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
114 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL
*NiiProtocol
;
117 Status
= gBS
->OpenProtocol (
119 &gEfiDevicePathProtocolGuid
,
121 This
->DriverBindingHandle
,
123 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
125 if (EFI_ERROR (Status
)) {
129 Status
= gBS
->OpenProtocol (
131 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
132 (VOID
**) &NiiProtocol
,
133 This
->DriverBindingHandle
,
135 EFI_OPEN_PROTOCOL_BY_DRIVER
138 if (EFI_ERROR (Status
)) {
139 if (Status
== EFI_ALREADY_STARTED
) {
140 DEBUG ((EFI_D_INFO
, "Support(): Already Started. on handle %p\n", Controller
));
145 DEBUG ((EFI_D_INFO
, "Support(): UNDI3.1 found on handle %p\n", Controller
));
148 // check the version, we don't want to connect to the undi16
150 if (NiiProtocol
->Type
!= EfiNetworkInterfaceUndi
) {
151 Status
= EFI_UNSUPPORTED
;
155 // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.
157 if (NiiProtocol
->ID
& 0x0F) {
158 DEBUG ((EFI_D_ERROR
| EFI_D_NET
, "\n!PXE structure is not paragraph aligned.\n"));
159 Status
= EFI_UNSUPPORTED
;
163 Pxe
= (PXE_UNDI
*) (UINTN
) (NiiProtocol
->ID
);
166 // Verify !PXE revisions.
168 if (Pxe
->hw
.Signature
!= PXE_ROMID_SIGNATURE
) {
169 DEBUG ((EFI_D_ERROR
| EFI_D_NET
, "\n!PXE signature is not valid.\n"));
170 Status
= EFI_UNSUPPORTED
;
174 if (Pxe
->hw
.Rev
< PXE_ROMID_REV
) {
175 DEBUG ((EFI_D_ERROR
| EFI_D_NET
, "\n!PXE.Rev is not supported.\n"));
176 Status
= EFI_UNSUPPORTED
;
180 if (Pxe
->hw
.MajorVer
< PXE_ROMID_MAJORVER
) {
182 DEBUG ((EFI_D_ERROR
| EFI_D_NET
, "\n!PXE.MajorVer is not supported.\n"));
183 Status
= EFI_UNSUPPORTED
;
186 } else if (Pxe
->hw
.MajorVer
== PXE_ROMID_MAJORVER
&& Pxe
->hw
.MinorVer
< PXE_ROMID_MINORVER
) {
187 DEBUG ((EFI_D_ERROR
| EFI_D_NET
, "\n!PXE.MinorVer is not supported."));
188 Status
= EFI_UNSUPPORTED
;
192 // Do S/W UNDI specific checks.
194 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_HW_UNDI
) == 0) {
195 if (Pxe
->sw
.EntryPoint
< Pxe
->sw
.Len
) {
196 DEBUG ((EFI_D_ERROR
| EFI_D_NET
, "\n!PXE S/W entry point is not valid."));
197 Status
= EFI_UNSUPPORTED
;
201 if (Pxe
->sw
.BusCnt
== 0) {
202 DEBUG ((EFI_D_ERROR
| EFI_D_NET
, "\n!PXE.BusCnt is zero."));
203 Status
= EFI_UNSUPPORTED
;
208 Status
= EFI_SUCCESS
;
209 DEBUG ((EFI_D_INFO
, "Support(): supported on %p\n", Controller
));
214 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
215 This
->DriverBindingHandle
,
223 Start this driver on ControllerHandle. This service is called by the
224 EFI boot service ConnectController(). In order to make
225 drivers as small as possible, there are a few calling restrictions for
226 this service. ConnectController() must follow these
227 calling restrictions. If any other agent wishes to call Start() it
228 must also follow these calling restrictions.
230 @param This Protocol instance pointer.
231 @param ControllerHandle Handle of device to bind driver to.
232 @param RemainingDevicePath Optional parameter use to pick a specific child
235 @retval EFI_SUCCESS This driver is added to ControllerHandle
236 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
237 @retval other This driver does not support this device
242 SimpleNetworkDriverStart (
243 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
244 IN EFI_HANDLE Controller
,
245 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
248 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL
*Nii
;
249 EFI_DEVICE_PATH_PROTOCOL
*NiiDevicePath
;
255 PXE_PCI_CONFIG_INFO ConfigInfo
;
256 PCI_TYPE00
*ConfigHeader
;
259 PXE_STATFLAGS InitStatFlags
;
261 DEBUG ((EFI_D_INFO
, "\nSnpNotifyNetworkInterfaceIdentifier() "));
263 Status
= gBS
->OpenProtocol (
265 &gEfiDevicePathProtocolGuid
,
266 (VOID
**) &NiiDevicePath
,
267 This
->DriverBindingHandle
,
269 EFI_OPEN_PROTOCOL_BY_DRIVER
272 if (EFI_ERROR (Status
)) {
276 Status
= gBS
->LocateDevicePath (
277 &gEfiPciIoProtocolGuid
,
282 if (EFI_ERROR (Status
)) {
286 Status
= gBS
->OpenProtocol (
288 &gEfiPciIoProtocolGuid
,
290 This
->DriverBindingHandle
,
292 EFI_OPEN_PROTOCOL_GET_PROTOCOL
294 if (EFI_ERROR (Status
)) {
298 // Get the NII interface.
300 Status
= gBS
->OpenProtocol (
302 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
304 This
->DriverBindingHandle
,
306 EFI_OPEN_PROTOCOL_BY_DRIVER
308 if (EFI_ERROR (Status
)) {
311 &gEfiDevicePathProtocolGuid
,
312 This
->DriverBindingHandle
,
318 DEBUG ((EFI_D_INFO
, "Start(): UNDI3.1 found\n"));
320 Pxe
= (PXE_UNDI
*) (UINTN
) (Nii
->ID
);
322 if (Calc8BitCksum (Pxe
, Pxe
->hw
.Len
) != 0) {
323 DEBUG ((EFI_D_ERROR
| EFI_D_NET
, "\n!PXE checksum is not correct.\n"));
327 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
) != 0) {
329 // We can get any packets.
331 } else if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
) != 0) {
333 // We need to be able to get broadcast packets for DHCP.
334 // If we do not have promiscuous support, we must at least have
335 // broadcast support or we cannot do DHCP!
338 DEBUG ((EFI_D_ERROR
| EFI_D_NET
, "\nUNDI does not have promiscuous or broadcast support."));
342 // OK, we like this UNDI, and we know snp is not already there on this handle
343 // Allocate and initialize a new simple network protocol structure.
345 Status
= mPciIo
->AllocateBuffer (
349 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
354 if (Status
!= EFI_SUCCESS
) {
355 DEBUG ((EFI_D_ERROR
| EFI_D_NET
, "\nCould not allocate SNP_DRIVER structure.\n"));
359 Snp
= (SNP_DRIVER
*) (UINTN
) Address
;
361 ZeroMem (Snp
, sizeof (SNP_DRIVER
));
364 Snp
->Signature
= SNP_DRIVER_SIGNATURE
;
366 EfiInitializeLock (&Snp
->Lock
, TPL_NOTIFY
);
368 Snp
->Snp
.Revision
= EFI_SIMPLE_NETWORK_PROTOCOL_REVISION
;
369 Snp
->Snp
.Start
= SnpUndi32Start
;
370 Snp
->Snp
.Stop
= SnpUndi32Stop
;
371 Snp
->Snp
.Initialize
= SnpUndi32Initialize
;
372 Snp
->Snp
.Reset
= SnpUndi32Reset
;
373 Snp
->Snp
.Shutdown
= SnpUndi32Shutdown
;
374 Snp
->Snp
.ReceiveFilters
= SnpUndi32ReceiveFilters
;
375 Snp
->Snp
.StationAddress
= SnpUndi32StationAddress
;
376 Snp
->Snp
.Statistics
= SnpUndi32Statistics
;
377 Snp
->Snp
.MCastIpToMac
= SnpUndi32McastIpToMac
;
378 Snp
->Snp
.NvData
= SnpUndi32NvData
;
379 Snp
->Snp
.GetStatus
= SnpUndi32GetStatus
;
380 Snp
->Snp
.Transmit
= SnpUndi32Transmit
;
381 Snp
->Snp
.Receive
= SnpUndi32Receive
;
382 Snp
->Snp
.WaitForPacket
= NULL
;
384 Snp
->Snp
.Mode
= &Snp
->Mode
;
386 Snp
->TxRxBufferSize
= 0;
387 Snp
->TxRxBuffer
= NULL
;
389 Snp
->IfNum
= Nii
->IfNum
;
391 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_HW_UNDI
) != 0) {
392 Snp
->IsSwUndi
= FALSE
;
393 Snp
->IssueUndi32Command
= &IssueHwUndiCommand
;
395 Snp
->IsSwUndi
= TRUE
;
397 if ((Pxe
->sw
.Implementation
& PXE_ROMID_IMP_SW_VIRT_ADDR
) != 0) {
398 Snp
->IssueUndi32Command
= (ISSUE_UNDI32_COMMAND
) (UINTN
) Pxe
->sw
.EntryPoint
;
400 Snp
->IssueUndi32Command
= (ISSUE_UNDI32_COMMAND
) (UINTN
) ((UINT8
) (UINTN
) Pxe
+ Pxe
->sw
.EntryPoint
);
404 // Allocate a global CPB and DB buffer for this UNDI interface.
405 // we do this because:
407 // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be
408 // within 2GB limit, create them here and map them so that when undi calls
409 // v2p callback to check if the physical address is < 2gb, we will pass.
411 // -This is not a requirement for 3.1 or later UNDIs but the code looks
412 // simpler if we use the same cpb, db variables for both old and new undi
413 // interfaces from all the SNP interface calls (we don't map the buffers
414 // for the newer undi interfaces though)
416 // -it is OK to allocate one global set of CPB, DB pair for each UNDI
417 // interface as EFI does not multi-task and so SNP will not be re-entered!
419 Status
= mPciIo
->AllocateBuffer (
423 SNP_MEM_PAGES (4096),
428 if (Status
!= EFI_SUCCESS
) {
429 DEBUG ((EFI_D_ERROR
| EFI_D_NET
, "\nCould not allocate CPB and DB structures.\n"));
430 goto Error_DeleteSNP
;
433 Snp
->Cpb
= (VOID
*) (UINTN
) Address
;
434 Snp
->Db
= (VOID
*) ((UINTN
) Address
+ 2048);
437 // PxeStart call is going to give the callback functions to UNDI, these callback
438 // functions use the BarIndex values from the snp structure, so these must be initialized
439 // with default values before doing a PxeStart. The correct values can be obtained after
440 // getting the config information from UNDI
442 Snp
->MemoryBarIndex
= 0;
446 // we need the undi init information many times in this snp code, just get it
447 // once here and store it in the snp driver structure. to get Init Info
448 // from UNDI we have to start undi first.
450 Status
= PxeStart (Snp
);
452 if (Status
!= EFI_SUCCESS
) {
453 goto Error_DeleteSNP
;
456 Snp
->Cdb
.OpCode
= PXE_OPCODE_GET_INIT_INFO
;
457 Snp
->Cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
459 Snp
->Cdb
.CPBsize
= PXE_CPBSIZE_NOT_USED
;
460 Snp
->Cdb
.CPBaddr
= PXE_DBADDR_NOT_USED
;
462 Snp
->Cdb
.DBsize
= sizeof Snp
->InitInfo
;
463 Snp
->Cdb
.DBaddr
= (UINT64
)(UINTN
) &Snp
->InitInfo
;
465 Snp
->Cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
466 Snp
->Cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
468 Snp
->Cdb
.IFnum
= Snp
->IfNum
;
469 Snp
->Cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
471 DEBUG ((EFI_D_INFO
| EFI_D_NET
, "\nSnp->undi.get_init_info() "));
473 (*Snp
->IssueUndi32Command
) ((UINT64
)(UINTN
) &Snp
->Cdb
);
476 // Save the INIT Stat Code...
478 InitStatFlags
= Snp
->Cdb
.StatFlags
;
480 if (Snp
->Cdb
.StatCode
!= PXE_STATCODE_SUCCESS
) {
481 DEBUG ((EFI_D_ERROR
| EFI_D_NET
, "\nSnp->undi.init_info() %xh:%xh\n", Snp
->Cdb
.StatFlags
, Snp
->Cdb
.StatCode
));
483 goto Error_DeleteSNP
;
486 Snp
->Cdb
.OpCode
= PXE_OPCODE_GET_CONFIG_INFO
;
487 Snp
->Cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
489 Snp
->Cdb
.CPBsize
= PXE_CPBSIZE_NOT_USED
;
490 Snp
->Cdb
.CPBaddr
= PXE_DBADDR_NOT_USED
;
492 Snp
->Cdb
.DBsize
= sizeof ConfigInfo
;
493 Snp
->Cdb
.DBaddr
= (UINT64
)(UINTN
) &ConfigInfo
;
495 Snp
->Cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
496 Snp
->Cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
498 Snp
->Cdb
.IFnum
= Snp
->IfNum
;
499 Snp
->Cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
501 DEBUG ((EFI_D_INFO
| EFI_D_NET
, "\nSnp->undi.get_config_info() "));
503 (*Snp
->IssueUndi32Command
) ((UINT64
)(UINTN
) &Snp
->Cdb
);
505 if (Snp
->Cdb
.StatCode
!= PXE_STATCODE_SUCCESS
) {
506 DEBUG ((EFI_D_ERROR
| EFI_D_NET
, "\nSnp->undi.config_info() %xh:%xh\n", Snp
->Cdb
.StatFlags
, Snp
->Cdb
.StatCode
));
508 goto Error_DeleteSNP
;
511 // Find the correct BAR to do IO.
514 // Enumerate through the PCI BARs for the device to determine which one is
515 // the IO BAR. Save the index of the BAR into the adapter info structure.
516 // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped
518 ConfigHeader
= (PCI_TYPE00
*) &ConfigInfo
.Config
.Byte
[0];
519 TempBar
= (UINT32
*) &ConfigHeader
->Device
.Bar
[0];
520 for (BarIndex
= 0; BarIndex
<= 5; BarIndex
++) {
521 if ((*TempBar
& PCI_BAR_MEM_MASK
) == PCI_BAR_MEM_64BIT
) {
523 // This is a 64-bit memory bar, skip this and the
529 if ((*TempBar
& PCI_BAR_IO_MASK
) == PCI_BAR_IO_MODE
) {
530 Snp
->IoBarIndex
= BarIndex
;
538 // Initialize simple network protocol mode structure
540 Snp
->Mode
.State
= EfiSimpleNetworkStopped
;
541 Snp
->Mode
.HwAddressSize
= Snp
->InitInfo
.HWaddrLen
;
542 Snp
->Mode
.MediaHeaderSize
= Snp
->InitInfo
.MediaHeaderLen
;
543 Snp
->Mode
.MaxPacketSize
= Snp
->InitInfo
.FrameDataLen
;
544 Snp
->Mode
.NvRamAccessSize
= Snp
->InitInfo
.NvWidth
;
545 Snp
->Mode
.NvRamSize
= Snp
->InitInfo
.NvCount
* Snp
->Mode
.NvRamAccessSize
;
546 Snp
->Mode
.IfType
= Snp
->InitInfo
.IFtype
;
547 Snp
->Mode
.MaxMCastFilterCount
= Snp
->InitInfo
.MCastFilterCnt
;
548 Snp
->Mode
.MCastFilterCount
= 0;
550 switch (InitStatFlags
& PXE_STATFLAGS_CABLE_DETECT_MASK
) {
551 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED
:
552 Snp
->Mode
.MediaPresentSupported
= TRUE
;
555 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED
:
557 Snp
->Mode
.MediaPresentSupported
= FALSE
;
560 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_STATION_ADDR_SETTABLE
) != 0) {
561 Snp
->Mode
.MacAddressChangeable
= TRUE
;
563 Snp
->Mode
.MacAddressChangeable
= FALSE
;
566 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED
) != 0) {
567 Snp
->Mode
.MultipleTxSupported
= TRUE
;
569 Snp
->Mode
.MultipleTxSupported
= FALSE
;
572 Snp
->Mode
.ReceiveFilterMask
= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
574 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
) != 0) {
575 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
579 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
) != 0) {
580 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
584 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
) != 0) {
585 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
589 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED
) != 0) {
590 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
594 if (Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
) {
595 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
599 Snp
->Mode
.ReceiveFilterSetting
= 0;
602 // need to get the station address to save in the mode structure. we need to
603 // initialize the UNDI first for this.
605 Snp
->TxRxBufferSize
= Snp
->InitInfo
.MemoryRequired
;
606 Status
= PxeInit (Snp
, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE
);
608 if (EFI_ERROR (Status
)) {
610 goto Error_DeleteSNP
;
613 Status
= PxeGetStnAddr (Snp
);
615 if (Status
!= EFI_SUCCESS
) {
616 DEBUG ((EFI_D_ERROR
, "\nSnp->undi.get_station_addr() failed.\n"));
619 goto Error_DeleteSNP
;
622 Snp
->Mode
.MediaPresent
= FALSE
;
625 // We should not leave UNDI started and initialized here. this DriverStart()
626 // routine must only find and attach the SNP interface to UNDI layer that it
627 // finds on the given handle!
628 // The UNDI layer will be started when upper layers call Snp->start.
629 // How ever, this DriverStart() must fill up the snp mode structure which
630 // contains the MAC address of the NIC. For this reason we started and
631 // initialized UNDI here, now we are done, do a shutdown and stop of the
638 // add SNP to the undi handle
640 Status
= gBS
->InstallProtocolInterface (
642 &gEfiSimpleNetworkProtocolGuid
,
643 EFI_NATIVE_INTERFACE
,
647 if (!EFI_ERROR (Status
)) {
651 Status
= mPciIo
->FreeBuffer (
653 SNP_MEM_PAGES (4096),
661 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
667 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
668 This
->DriverBindingHandle
,
674 &gEfiDevicePathProtocolGuid
,
675 This
->DriverBindingHandle
,
683 Stop this driver on ControllerHandle. This service is called by the
684 EFI boot service DisconnectController(). In order to
685 make drivers as small as possible, there are a few calling
686 restrictions for this service. DisconnectController()
687 must follow these calling restrictions. If any other agent wishes
688 to call Stop() it must also follow these calling restrictions.
690 @param This Protocol instance pointer.
691 @param ControllerHandle Handle of device to stop driver on
692 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
693 children is zero stop the entire bus driver.
694 @param ChildHandleBuffer List of Child Handles to Stop.
696 @retval EFI_SUCCESS This driver is removed ControllerHandle
697 @retval other This driver was not removed from this device
702 SimpleNetworkDriverStop (
703 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
704 IN EFI_HANDLE Controller
,
705 IN UINTN NumberOfChildren
,
706 IN EFI_HANDLE
*ChildHandleBuffer
710 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpProtocol
;
714 // Get our context back.
716 Status
= gBS
->OpenProtocol (
718 &gEfiSimpleNetworkProtocolGuid
,
719 (VOID
**) &SnpProtocol
,
720 This
->DriverBindingHandle
,
722 EFI_OPEN_PROTOCOL_GET_PROTOCOL
725 if (EFI_ERROR (Status
)) {
726 return EFI_UNSUPPORTED
;
729 Snp
= EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol
);
731 Status
= gBS
->UninstallProtocolInterface (
733 &gEfiSimpleNetworkProtocolGuid
,
737 if (EFI_ERROR (Status
)) {
741 Status
= gBS
->CloseProtocol (
743 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
744 This
->DriverBindingHandle
,
748 Status
= gBS
->CloseProtocol (
750 &gEfiDevicePathProtocolGuid
,
751 This
->DriverBindingHandle
,
760 SNP_MEM_PAGES (4096),
766 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
774 // Simple Network Protocol Driver Global Variables
776 EFI_DRIVER_BINDING_PROTOCOL mSimpleNetworkDriverBinding
= {
777 SimpleNetworkDriverSupported
,
778 SimpleNetworkDriverStart
,
779 SimpleNetworkDriverStop
,
787 This routine maps the given CPU address to a Device address. It creates a
788 an entry in the map list with the virtual and physical addresses and the
791 @param V2p pointer to return a map list node pointer.
792 @param Type the direction in which the data flows from the given
793 virtual address device->cpu or cpu->device or both
795 @param VirtualAddress virtual address (or CPU address) to be mapped.
796 @param BufferSize size of the buffer to be mapped.
798 @retval EFI_SUCEESS routine has completed the mapping.
799 @retval EFI_INVALID_PARAMETER invalid parameter.
800 @retval EFI_OUT_OF_RESOURCES out of resource.
801 @retval other error as indicated.
807 EFI_PCI_IO_PROTOCOL_OPERATION Type
,
808 VOID
*VirtualAddress
,
814 if ((V2p
== NULL
) || (VirtualAddress
== NULL
) || (BufferSize
== 0)) {
815 return EFI_INVALID_PARAMETER
;
818 *V2p
= AllocatePool (sizeof (V2P
));
820 return EFI_OUT_OF_RESOURCES
;
823 Status
= mPciIo
->Map (
828 &(*V2p
)->PhysicalAddress
,
831 if (Status
!= EFI_SUCCESS
) {
835 (*V2p
)->VirtualAddress
= VirtualAddress
;
836 (*V2p
)->BufferSize
= BufferSize
;
845 This routine searches the linked list of mapped address nodes (for undi3.0
846 interface) to find the node that corresponds to the given virtual address and
847 returns a pointer to that node.
849 @param V2p pointer to return a map list node pointer.
850 @param VirtualAddr virtual address (or CPU address) to be searched in
853 @retval EFI_SUCEESS A match was found.
854 @retval Other A match cannot be found.
865 if (V2p
== NULL
|| VirtualAddr
== NULL
) {
866 return EFI_INVALID_PARAMETER
;
869 for (Ptr
= mV2p
; Ptr
!= NULL
; Ptr
= Ptr
->Next
) {
870 if (Ptr
->VirtualAddress
== VirtualAddr
) {
876 return EFI_NOT_FOUND
;
881 Unmap the given virtual address and free the memory allocated for the map list
882 node corresponding to that address.
884 @param VirtualAddress virtual address (or CPU address) to be unmapped.
886 @retval EFI_SUCEESS Successfully unmapped.
887 @retval Other Other errors as indicated.
899 if (VirtualAddress
== NULL
) {
900 return EFI_INVALID_PARAMETER
;
904 return EFI_NOT_FOUND
;
907 // Is our node at the head of the list??
909 if ((Current
= mV2p
)->VirtualAddress
== VirtualAddress
) {
912 Status
= mPciIo
->Unmap (mPciIo
, Current
->Unmap
);
916 if (EFI_ERROR (Status
)) {
917 DEBUG ((EFI_D_ERROR
, "Unmap failed with status = %r\n", Status
));
922 for (; Current
->Next
!= NULL
; Current
= Next
) {
923 if ((Next
= Current
->Next
)->VirtualAddress
== VirtualAddress
) {
924 Current
->Next
= Next
->Next
;
925 Status
= mPciIo
->Unmap (mPciIo
, Next
->Unmap
);
928 if (EFI_ERROR (Status
)) {
929 DEBUG ((EFI_D_ERROR
, "Unmap failed with status = %r\n", Status
));
935 return EFI_NOT_FOUND
;
939 The SNP driver entry point.
941 @param ImageHandle The driver image handle.
942 @param SystemTable The system table.
944 @retval EFI_SUCEESS Initialization routine has found UNDI hardware,
945 loaded it's ROM, and installed a notify event for
946 the Network Indentifier Interface Protocol
948 @retval Other Return value from HandleProtocol for
949 DeviceIoProtocol or LoadedImageProtocol
954 InitializeSnpNiiDriver (
955 IN EFI_HANDLE ImageHandle
,
956 IN EFI_SYSTEM_TABLE
*SystemTable
959 return EfiLibInstallDriverBindingComponentName2 (
962 &mSimpleNetworkDriverBinding
,
964 &gSimpleNetworkComponentName
,
965 &gSimpleNetworkComponentName2