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
29 @param Cdb command to be sent to UNDI.
37 DEBUG ((EFI_D_ERROR
, "\nIssueHwUndiCommand() - This should not be called!"));
40 return EFI_INVALID_PARAMETER
;
44 // %%TBD - For now, nothing is done.
46 return EFI_UNSUPPORTED
;
51 Compute 8-bit checksum of a buffer.
53 @param Buffer Pointer to buffer.
54 @param Length Length of buffer in bytes.
56 @return 8-bit checksum of all bytes in buffer.
57 @return If ptr is NULL or len is zero, zero is returned.
72 if (Ptr
== NULL
|| Length
== 0) {
76 while (Length
-- != 0) {
77 Cksum
= (UINT8
) (Cksum
+ *Ptr
++);
84 Test to see if this driver supports ControllerHandle. This service
85 is called by the EFI boot service ConnectController(). In
86 order to make drivers as small as possible, there are a few calling
87 restrictions for this service. ConnectController() must
88 follow these calling restrictions. If any other agent wishes to call
89 Supported() it must also follow these calling restrictions.
91 @param This Protocol instance pointer.
92 @param ControllerHandle Handle of device to test
93 @param RemainingDevicePath Optional parameter use to pick a specific child
96 @retval EFI_SUCCESS This driver supports this device
97 @retval EFI_ALREADY_STARTED This driver is already running on this device
98 @retval other This driver does not support this device
103 SimpleNetworkDriverSupported (
104 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
105 IN EFI_HANDLE Controller
,
106 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
110 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL
*NiiProtocol
;
113 Status
= gBS
->OpenProtocol (
115 &gEfiDevicePathProtocolGuid
,
117 This
->DriverBindingHandle
,
119 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
121 if (EFI_ERROR (Status
)) {
125 Status
= gBS
->OpenProtocol (
127 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
128 (VOID
**) &NiiProtocol
,
129 This
->DriverBindingHandle
,
131 EFI_OPEN_PROTOCOL_BY_DRIVER
134 if (EFI_ERROR (Status
)) {
135 if (Status
== EFI_ALREADY_STARTED
) {
136 DEBUG ((EFI_D_INFO
, "Support(): Already Started. on handle %p\n", Controller
));
141 DEBUG ((EFI_D_INFO
, "Support(): UNDI3.1 found on handle %p\n", Controller
));
144 // check the version, we don't want to connect to the undi16
146 if (NiiProtocol
->Type
!= EfiNetworkInterfaceUndi
) {
147 Status
= EFI_UNSUPPORTED
;
151 // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.
153 if (NiiProtocol
->ID
& 0x0F) {
154 DEBUG ((EFI_D_NET
, "\n!PXE structure is not paragraph aligned.\n"));
155 Status
= EFI_UNSUPPORTED
;
159 Pxe
= (PXE_UNDI
*) (UINTN
) (NiiProtocol
->ID
);
162 // Verify !PXE revisions.
164 if (Pxe
->hw
.Signature
!= PXE_ROMID_SIGNATURE
) {
165 DEBUG ((EFI_D_NET
, "\n!PXE signature is not valid.\n"));
166 Status
= EFI_UNSUPPORTED
;
170 if (Pxe
->hw
.Rev
< PXE_ROMID_REV
) {
171 DEBUG ((EFI_D_NET
, "\n!PXE.Rev is not supported.\n"));
172 Status
= EFI_UNSUPPORTED
;
176 if (Pxe
->hw
.MajorVer
< PXE_ROMID_MAJORVER
) {
178 DEBUG ((EFI_D_NET
, "\n!PXE.MajorVer is not supported.\n"));
179 Status
= EFI_UNSUPPORTED
;
182 } else if (Pxe
->hw
.MajorVer
== PXE_ROMID_MAJORVER
&& Pxe
->hw
.MinorVer
< PXE_ROMID_MINORVER
) {
183 DEBUG ((EFI_D_NET
, "\n!PXE.MinorVer is not supported."));
184 Status
= EFI_UNSUPPORTED
;
188 // Do S/W UNDI specific checks.
190 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_HW_UNDI
) == 0) {
191 if (Pxe
->sw
.EntryPoint
< Pxe
->sw
.Len
) {
192 DEBUG ((EFI_D_NET
, "\n!PXE S/W entry point is not valid."));
193 Status
= EFI_UNSUPPORTED
;
197 if (Pxe
->sw
.BusCnt
== 0) {
198 DEBUG ((EFI_D_NET
, "\n!PXE.BusCnt is zero."));
199 Status
= EFI_UNSUPPORTED
;
204 Status
= EFI_SUCCESS
;
205 DEBUG ((EFI_D_INFO
, "Support(): supported on %p\n", Controller
));
210 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
211 This
->DriverBindingHandle
,
219 Start this driver on ControllerHandle. This service is called by the
220 EFI boot service ConnectController(). In order to make
221 drivers as small as possible, there are a few calling restrictions for
222 this service. ConnectController() must follow these
223 calling restrictions. If any other agent wishes to call Start() it
224 must also follow these calling restrictions.
226 @param This Protocol instance pointer.
227 @param ControllerHandle Handle of device to bind driver to.
228 @param RemainingDevicePath Optional parameter use to pick a specific child
231 @retval EFI_SUCCESS This driver is added to ControllerHandle
232 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
233 @retval other This driver does not support this device
238 SimpleNetworkDriverStart (
239 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
240 IN EFI_HANDLE Controller
,
241 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
244 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL
*Nii
;
245 EFI_DEVICE_PATH_PROTOCOL
*NiiDevicePath
;
251 PXE_PCI_CONFIG_INFO ConfigInfo
;
252 PCI_TYPE00
*ConfigHeader
;
255 PXE_STATFLAGS InitStatFlags
;
257 DEBUG ((EFI_D_NET
, "\nSnpNotifyNetworkInterfaceIdentifier() "));
259 Status
= gBS
->OpenProtocol (
261 &gEfiDevicePathProtocolGuid
,
262 (VOID
**) &NiiDevicePath
,
263 This
->DriverBindingHandle
,
265 EFI_OPEN_PROTOCOL_BY_DRIVER
268 if (EFI_ERROR (Status
)) {
272 Status
= gBS
->LocateDevicePath (
273 &gEfiPciIoProtocolGuid
,
278 if (EFI_ERROR (Status
)) {
282 Status
= gBS
->OpenProtocol (
284 &gEfiPciIoProtocolGuid
,
286 This
->DriverBindingHandle
,
288 EFI_OPEN_PROTOCOL_GET_PROTOCOL
290 if (EFI_ERROR (Status
)) {
294 // Get the NII interface.
296 Status
= gBS
->OpenProtocol (
298 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
300 This
->DriverBindingHandle
,
302 EFI_OPEN_PROTOCOL_BY_DRIVER
304 if (EFI_ERROR (Status
)) {
307 &gEfiDevicePathProtocolGuid
,
308 This
->DriverBindingHandle
,
314 DEBUG ((EFI_D_INFO
, "Start(): UNDI3.1 found\n"));
316 Pxe
= (PXE_UNDI
*) (UINTN
) (Nii
->ID
);
318 if (Calc8BitCksum (Pxe
, Pxe
->hw
.Len
) != 0) {
319 DEBUG ((EFI_D_NET
, "\n!PXE checksum is not correct.\n"));
323 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
) != 0) {
325 // We can get any packets.
327 } else if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
) != 0) {
329 // We need to be able to get broadcast packets for DHCP.
330 // If we do not have promiscuous support, we must at least have
331 // broadcast support or we cannot do DHCP!
334 DEBUG ((EFI_D_NET
, "\nUNDI does not have promiscuous or broadcast support."));
338 // OK, we like this UNDI, and we know snp is not already there on this handle
339 // Allocate and initialize a new simple network protocol structure.
341 Status
= mPciIo
->AllocateBuffer (
345 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
350 if (Status
!= EFI_SUCCESS
) {
351 DEBUG ((EFI_D_NET
, "\nCould not allocate SNP_DRIVER structure.\n"));
355 Snp
= (SNP_DRIVER
*) (UINTN
) Address
;
357 ZeroMem (Snp
, sizeof (SNP_DRIVER
));
360 Snp
->Signature
= SNP_DRIVER_SIGNATURE
;
362 EfiInitializeLock (&Snp
->Lock
, TPL_NOTIFY
);
364 Snp
->Snp
.Revision
= EFI_SIMPLE_NETWORK_PROTOCOL_REVISION
;
365 Snp
->Snp
.Start
= SnpUndi32Start
;
366 Snp
->Snp
.Stop
= SnpUndi32Stop
;
367 Snp
->Snp
.Initialize
= SnpUndi32Initialize
;
368 Snp
->Snp
.Reset
= SnpUndi32Reset
;
369 Snp
->Snp
.Shutdown
= SnpUndi32Shutdown
;
370 Snp
->Snp
.ReceiveFilters
= SnpUndi32ReceiveFilters
;
371 Snp
->Snp
.StationAddress
= SnpUndi32StationAddress
;
372 Snp
->Snp
.Statistics
= SnpUndi32Statistics
;
373 Snp
->Snp
.MCastIpToMac
= SnpUndi32McastIpToMac
;
374 Snp
->Snp
.NvData
= SnpUndi32NvData
;
375 Snp
->Snp
.GetStatus
= SnpUndi32GetStatus
;
376 Snp
->Snp
.Transmit
= SnpUndi32Transmit
;
377 Snp
->Snp
.Receive
= SnpUndi32Receive
;
378 Snp
->Snp
.WaitForPacket
= NULL
;
380 Snp
->Snp
.Mode
= &Snp
->Mode
;
382 Snp
->TxRxBufferSize
= 0;
383 Snp
->TxRxBuffer
= NULL
;
385 Snp
->IfNum
= Nii
->IfNum
;
387 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_HW_UNDI
) != 0) {
388 Snp
->IsSwUndi
= FALSE
;
389 Snp
->IssueUndi32Command
= &IssueHwUndiCommand
;
391 Snp
->IsSwUndi
= TRUE
;
393 if ((Pxe
->sw
.Implementation
& PXE_ROMID_IMP_SW_VIRT_ADDR
) != 0) {
394 Snp
->IssueUndi32Command
= (ISSUE_UNDI32_COMMAND
) (UINTN
) Pxe
->sw
.EntryPoint
;
396 Snp
->IssueUndi32Command
= (ISSUE_UNDI32_COMMAND
) (UINTN
) ((UINT8
) (UINTN
) Pxe
+ Pxe
->sw
.EntryPoint
);
400 // Allocate a global CPB and DB buffer for this UNDI interface.
401 // we do this because:
403 // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be
404 // within 2GB limit, create them here and map them so that when undi calls
405 // v2p callback to check if the physical address is < 2gb, we will pass.
407 // -This is not a requirement for 3.1 or later UNDIs but the code looks
408 // simpler if we use the same cpb, db variables for both old and new undi
409 // interfaces from all the SNP interface calls (we don't map the buffers
410 // for the newer undi interfaces though)
412 // -it is OK to allocate one global set of CPB, DB pair for each UNDI
413 // interface as EFI does not multi-task and so SNP will not be re-entered!
415 Status
= mPciIo
->AllocateBuffer (
419 SNP_MEM_PAGES (4096),
424 if (Status
!= EFI_SUCCESS
) {
425 DEBUG ((EFI_D_NET
, "\nCould not allocate CPB and DB structures.\n"));
426 goto Error_DeleteSNP
;
429 Snp
->Cpb
= (VOID
*) (UINTN
) Address
;
430 Snp
->Db
= (VOID
*) ((UINTN
) Address
+ 2048);
433 // PxeStart call is going to give the callback functions to UNDI, these callback
434 // functions use the BarIndex values from the snp structure, so these must be initialized
435 // with default values before doing a PxeStart. The correct values can be obtained after
436 // getting the config information from UNDI
438 Snp
->MemoryBarIndex
= 0;
442 // we need the undi init information many times in this snp code, just get it
443 // once here and store it in the snp driver structure. to get Init Info
444 // from UNDI we have to start undi first.
446 Status
= PxeStart (Snp
);
448 if (Status
!= EFI_SUCCESS
) {
449 goto Error_DeleteSNP
;
452 Snp
->Cdb
.OpCode
= PXE_OPCODE_GET_INIT_INFO
;
453 Snp
->Cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
455 Snp
->Cdb
.CPBsize
= PXE_CPBSIZE_NOT_USED
;
456 Snp
->Cdb
.CPBaddr
= PXE_DBADDR_NOT_USED
;
458 Snp
->Cdb
.DBsize
= sizeof Snp
->InitInfo
;
459 Snp
->Cdb
.DBaddr
= (UINT64
)(UINTN
) &Snp
->InitInfo
;
461 Snp
->Cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
462 Snp
->Cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
464 Snp
->Cdb
.IFnum
= Snp
->IfNum
;
465 Snp
->Cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
467 DEBUG ((EFI_D_NET
, "\nSnp->undi.get_init_info() "));
469 (*Snp
->IssueUndi32Command
) ((UINT64
)(UINTN
) &Snp
->Cdb
);
472 // Save the INIT Stat Code...
474 InitStatFlags
= Snp
->Cdb
.StatFlags
;
476 if (Snp
->Cdb
.StatCode
!= PXE_STATCODE_SUCCESS
) {
477 DEBUG ((EFI_D_NET
, "\nSnp->undi.init_info() %xh:%xh\n", Snp
->Cdb
.StatFlags
, Snp
->Cdb
.StatCode
));
479 goto Error_DeleteSNP
;
482 Snp
->Cdb
.OpCode
= PXE_OPCODE_GET_CONFIG_INFO
;
483 Snp
->Cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
485 Snp
->Cdb
.CPBsize
= PXE_CPBSIZE_NOT_USED
;
486 Snp
->Cdb
.CPBaddr
= PXE_DBADDR_NOT_USED
;
488 Snp
->Cdb
.DBsize
= sizeof ConfigInfo
;
489 Snp
->Cdb
.DBaddr
= (UINT64
)(UINTN
) &ConfigInfo
;
491 Snp
->Cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
492 Snp
->Cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
494 Snp
->Cdb
.IFnum
= Snp
->IfNum
;
495 Snp
->Cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
497 DEBUG ((EFI_D_NET
, "\nSnp->undi.get_config_info() "));
499 (*Snp
->IssueUndi32Command
) ((UINT64
)(UINTN
) &Snp
->Cdb
);
501 if (Snp
->Cdb
.StatCode
!= PXE_STATCODE_SUCCESS
) {
502 DEBUG ((EFI_D_NET
, "\nSnp->undi.config_info() %xh:%xh\n", Snp
->Cdb
.StatFlags
, Snp
->Cdb
.StatCode
));
504 goto Error_DeleteSNP
;
507 // Find the correct BAR to do IO.
510 // Enumerate through the PCI BARs for the device to determine which one is
511 // the IO BAR. Save the index of the BAR into the adapter info structure.
512 // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped
514 ConfigHeader
= (PCI_TYPE00
*) &ConfigInfo
.Config
.Byte
[0];
515 TempBar
= (UINT32
*) &ConfigHeader
->Device
.Bar
[0];
516 for (BarIndex
= 0; BarIndex
<= 5; BarIndex
++) {
517 if ((*TempBar
& PCI_BAR_MEM_MASK
) == PCI_BAR_MEM_64BIT
) {
519 // This is a 64-bit memory bar, skip this and the
525 if ((*TempBar
& PCI_BAR_IO_MASK
) == PCI_BAR_IO_MODE
) {
526 Snp
->IoBarIndex
= BarIndex
;
534 // Initialize simple network protocol mode structure
536 Snp
->Mode
.State
= EfiSimpleNetworkStopped
;
537 Snp
->Mode
.HwAddressSize
= Snp
->InitInfo
.HWaddrLen
;
538 Snp
->Mode
.MediaHeaderSize
= Snp
->InitInfo
.MediaHeaderLen
;
539 Snp
->Mode
.MaxPacketSize
= Snp
->InitInfo
.FrameDataLen
;
540 Snp
->Mode
.NvRamAccessSize
= Snp
->InitInfo
.NvWidth
;
541 Snp
->Mode
.NvRamSize
= Snp
->InitInfo
.NvCount
* Snp
->Mode
.NvRamAccessSize
;
542 Snp
->Mode
.IfType
= Snp
->InitInfo
.IFtype
;
543 Snp
->Mode
.MaxMCastFilterCount
= Snp
->InitInfo
.MCastFilterCnt
;
544 Snp
->Mode
.MCastFilterCount
= 0;
546 switch (InitStatFlags
& PXE_STATFLAGS_CABLE_DETECT_MASK
) {
547 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED
:
548 Snp
->Mode
.MediaPresentSupported
= TRUE
;
551 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED
:
553 Snp
->Mode
.MediaPresentSupported
= FALSE
;
556 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_STATION_ADDR_SETTABLE
) != 0) {
557 Snp
->Mode
.MacAddressChangeable
= TRUE
;
559 Snp
->Mode
.MacAddressChangeable
= FALSE
;
562 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED
) != 0) {
563 Snp
->Mode
.MultipleTxSupported
= TRUE
;
565 Snp
->Mode
.MultipleTxSupported
= FALSE
;
568 Snp
->Mode
.ReceiveFilterMask
= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
570 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
) != 0) {
571 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
575 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
) != 0) {
576 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
580 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
) != 0) {
581 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
585 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED
) != 0) {
586 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
590 if (Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
) {
591 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
595 Snp
->Mode
.ReceiveFilterSetting
= 0;
598 // need to get the station address to save in the mode structure. we need to
599 // initialize the UNDI first for this.
601 Snp
->TxRxBufferSize
= Snp
->InitInfo
.MemoryRequired
;
602 Status
= PxeInit (Snp
, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE
);
604 if (EFI_ERROR (Status
)) {
606 goto Error_DeleteSNP
;
609 Status
= PxeGetStnAddr (Snp
);
611 if (Status
!= EFI_SUCCESS
) {
612 DEBUG ((EFI_D_ERROR
, "\nSnp->undi.get_station_addr() failed.\n"));
615 goto Error_DeleteSNP
;
618 Snp
->Mode
.MediaPresent
= FALSE
;
621 // We should not leave UNDI started and initialized here. this DriverStart()
622 // routine must only find and attach the SNP interface to UNDI layer that it
623 // finds on the given handle!
624 // The UNDI layer will be started when upper layers call Snp->start.
625 // How ever, this DriverStart() must fill up the snp mode structure which
626 // contains the MAC address of the NIC. For this reason we started and
627 // initialized UNDI here, now we are done, do a shutdown and stop of the
634 // add SNP to the undi handle
636 Status
= gBS
->InstallProtocolInterface (
638 &gEfiSimpleNetworkProtocolGuid
,
639 EFI_NATIVE_INTERFACE
,
643 if (!EFI_ERROR (Status
)) {
647 Status
= mPciIo
->FreeBuffer (
649 SNP_MEM_PAGES (4096),
657 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
663 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
664 This
->DriverBindingHandle
,
670 &gEfiDevicePathProtocolGuid
,
671 This
->DriverBindingHandle
,
679 Stop this driver on ControllerHandle. This service is called by the
680 EFI boot service DisconnectController(). In order to
681 make drivers as small as possible, there are a few calling
682 restrictions for this service. DisconnectController()
683 must follow these calling restrictions. If any other agent wishes
684 to call Stop() it must also follow these calling restrictions.
686 @param This Protocol instance pointer.
687 @param ControllerHandle Handle of device to stop driver on
688 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
689 children is zero stop the entire bus driver.
690 @param ChildHandleBuffer List of Child Handles to Stop.
692 @retval EFI_SUCCESS This driver is removed ControllerHandle
693 @retval other This driver was not removed from this device
698 SimpleNetworkDriverStop (
699 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
700 IN EFI_HANDLE Controller
,
701 IN UINTN NumberOfChildren
,
702 IN EFI_HANDLE
*ChildHandleBuffer
706 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpProtocol
;
710 // Get our context back.
712 Status
= gBS
->OpenProtocol (
714 &gEfiSimpleNetworkProtocolGuid
,
715 (VOID
**) &SnpProtocol
,
716 This
->DriverBindingHandle
,
718 EFI_OPEN_PROTOCOL_GET_PROTOCOL
721 if (EFI_ERROR (Status
)) {
722 return EFI_UNSUPPORTED
;
725 Snp
= EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol
);
727 Status
= gBS
->UninstallProtocolInterface (
729 &gEfiSimpleNetworkProtocolGuid
,
733 if (EFI_ERROR (Status
)) {
737 Status
= gBS
->CloseProtocol (
739 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
740 This
->DriverBindingHandle
,
744 Status
= gBS
->CloseProtocol (
746 &gEfiDevicePathProtocolGuid
,
747 This
->DriverBindingHandle
,
756 SNP_MEM_PAGES (4096),
762 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
770 // Simple Network Protocol Driver Global Variables
772 EFI_DRIVER_BINDING_PROTOCOL mSimpleNetworkDriverBinding
= {
773 SimpleNetworkDriverSupported
,
774 SimpleNetworkDriverStart
,
775 SimpleNetworkDriverStop
,
783 This routine maps the given CPU address to a Device address. It creates a
784 an entry in the map list with the virtual and physical addresses and the
787 @param V2p pointer to return a map list node pointer.
788 @param Type the direction in which the data flows from the given
789 virtual address device->cpu or cpu->device or both
791 @param VirtualAddress virtual address (or CPU address) to be mapped.
792 @param BufferSize size of the buffer to be mapped.
794 @retval EFI_SUCEESS routine has completed the mapping.
795 @retval EFI_INVALID_PARAMETER invalid parameter.
796 @retval EFI_OUT_OF_RESOURCES out of resource.
797 @retval other error as indicated.
803 EFI_PCI_IO_PROTOCOL_OPERATION Type
,
804 VOID
*VirtualAddress
,
810 if ((V2p
== NULL
) || (VirtualAddress
== NULL
) || (BufferSize
== 0)) {
811 return EFI_INVALID_PARAMETER
;
814 *V2p
= AllocatePool (sizeof (V2P
));
816 return EFI_OUT_OF_RESOURCES
;
819 Status
= mPciIo
->Map (
824 &(*V2p
)->PhysicalAddress
,
827 if (Status
!= EFI_SUCCESS
) {
831 (*V2p
)->VirtualAddress
= VirtualAddress
;
832 (*V2p
)->BufferSize
= BufferSize
;
841 This routine searches the linked list of mapped address nodes (for undi3.0
842 interface) to find the node that corresponds to the given virtual address and
843 returns a pointer to that node.
845 @param V2p pointer to return a map list node pointer.
846 @param VirtualAddr virtual address (or CPU address) to be searched in
849 @retval EFI_SUCEESS if a match found!
850 @retval Other match not found
861 if (V2p
== NULL
|| VirtualAddr
== NULL
) {
862 return EFI_INVALID_PARAMETER
;
865 for (Ptr
= mV2p
; Ptr
!= NULL
; Ptr
= Ptr
->Next
) {
866 if (Ptr
->VirtualAddress
== VirtualAddr
) {
872 return EFI_NOT_FOUND
;
877 This routine unmaps the given virtual address and frees the memory allocated
878 for the map list node corresponding to that address.
880 @param VirtualAddress virtual address (or CPU address) to be unmapped
882 @retval EFI_SUCEESS if successfully unmapped
883 @retval Other as indicated by the error
895 if (VirtualAddress
== NULL
) {
896 return EFI_INVALID_PARAMETER
;
900 return EFI_NOT_FOUND
;
903 // Is our node at the head of the list??
905 if ((Current
= mV2p
)->VirtualAddress
== VirtualAddress
) {
908 Status
= mPciIo
->Unmap (mPciIo
, Current
->Unmap
);
912 if (EFI_ERROR (Status
)) {
913 DEBUG ((EFI_D_ERROR
, "Unmap failed with status = %r\n", Status
));
918 for (; Current
->Next
!= NULL
; Current
= Next
) {
919 if ((Next
= Current
->Next
)->VirtualAddress
== VirtualAddress
) {
920 Current
->Next
= Next
->Next
;
921 Status
= mPciIo
->Unmap (mPciIo
, Next
->Unmap
);
924 if (EFI_ERROR (Status
)) {
925 DEBUG ((EFI_D_ERROR
, "Unmap failed with status = %r\n", Status
));
931 return EFI_NOT_FOUND
;
935 The SNP driver entry point.
937 @param ImageHandle The driver image handle.
938 @param SystemTable The system table.
940 @retval EFI_SUCEESS Initialization routine has found UNDI hardware,
941 loaded it's ROM, and installed a notify event for
942 the Network Indentifier Interface Protocol
944 @retval Other Return value from HandleProtocol for
945 DeviceIoProtocol or LoadedImageProtocol
950 InitializeSnpNiiDriver (
951 IN EFI_HANDLE ImageHandle
,
952 IN EFI_SYSTEM_TABLE
*SystemTable
955 return EfiLibInstallDriverBindingComponentName2 (
958 &mSimpleNetworkDriverBinding
,
960 &gSimpleNetworkComponentName
,
961 &gSimpleNetworkComponentName2