2 Copyright (c) 2004 - 2005, Intel Corporation
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
45 InitializeSnpNiiDriver (
46 IN EFI_HANDLE image_handle
,
47 IN EFI_SYSTEM_TABLE
*system_table
52 SimpleNetworkDriverSupported (
53 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
54 IN EFI_HANDLE Controller
,
55 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
60 SimpleNetworkDriverStart (
61 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
62 IN EFI_HANDLE Controller
,
63 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
68 SimpleNetworkDriverStop (
69 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
70 IN EFI_HANDLE Controller
,
71 IN UINTN NumberOfChildren
,
72 IN EFI_HANDLE
*ChildHandleBuffer
76 // Simple Network Protocol Driver Global Variables
78 EFI_DRIVER_BINDING_PROTOCOL mSimpleNetworkDriverBinding
= {
79 SimpleNetworkDriverSupported
,
80 SimpleNetworkDriverStart
,
81 SimpleNetworkDriverStop
,
88 // Module global variables needed to support undi 3.0 interface
90 EFI_PCI_IO_PROTOCOL
*mPciIoFncs
;
91 struct s_v2p
*_v2p
= NULL
; // undi3.0 map_list head
92 // End Global variables
96 This routine maps the given CPU address to a Device address. It creates a
97 an entry in the map list with the virtual and physical addresses and the
100 @param v2p pointer to return a map list node pointer.
101 @param type the direction in which the data flows from the given
102 virtual address device->cpu or cpu->device or both
104 @param vaddr virtual address (or CPU address) to be mapped
105 @param bsize size of the buffer to be mapped.
107 @retval EFI_SUCEESS routine has completed the mapping
108 @retval other error as indicated.
113 IN OUT
struct s_v2p
**v2p
,
114 EFI_PCI_IO_PROTOCOL_OPERATION type
,
121 if ((v2p
== NULL
) || (vaddr
== NULL
) || (bsize
== 0)) {
122 return EFI_INVALID_PARAMETER
;
125 *v2p
= AllocatePool (sizeof (struct s_v2p
));
127 return EFI_OUT_OF_RESOURCES
;
130 Status
= mPciIoFncs
->Map (
138 if (Status
!= EFI_SUCCESS
) {
142 (*v2p
)->vaddr
= vaddr
;
143 (*v2p
)->bsize
= bsize
;
152 This routine searches the linked list of mapped address nodes (for undi3.0
153 interface) to find the node that corresponds to the given virtual address and
154 returns a pointer to that node.
156 @param v2p pointer to return a map list node pointer.
157 @param vaddr virtual address (or CPU address) to be searched in
160 @retval EFI_SUCEESS if a match found!
161 @retval Other match not found
172 if (v2p
== NULL
|| vaddr
== NULL
) {
173 return EFI_INVALID_PARAMETER
;
176 for (v
= _v2p
; v
!= NULL
; v
= v
->next
) {
177 if (v
->vaddr
== vaddr
) {
183 return EFI_NOT_FOUND
;
188 This routine unmaps the given virtual address and frees the memory allocated
189 for the map list node corresponding to that address.
191 @param vaddr virtual address (or CPU address) to be unmapped
193 @retval EFI_SUCEESS if successfully unmapped
194 @retval Other as indicated by the error
207 return EFI_INVALID_PARAMETER
;
211 return EFI_NOT_FOUND
;
214 // Is our node at the head of the list??
216 if ((v
= _v2p
)->vaddr
== vaddr
) {
219 Status
= mPciIoFncs
->Unmap (mPciIoFncs
, v
->unmap
);
224 DEBUG ((EFI_D_ERROR
, "Unmap failed with status = %x\n", Status
));
229 for (; v
->next
!= NULL
; v
= t
) {
230 if ((t
= v
->next
)->vaddr
== vaddr
) {
232 Status
= mPciIoFncs
->Unmap (mPciIoFncs
, t
->unmap
);
236 DEBUG ((EFI_D_ERROR
, "Unmap failed with status = %x\n", Status
));
242 return EFI_NOT_FOUND
;
247 issue_hwundi_command (
260 DEBUG ((EFI_D_ERROR
, "\nissue_hwundi_command() - This should not be called!"));
263 return EFI_INVALID_PARAMETER
;
267 // %%TBD - For now, nothing is done.
269 return EFI_UNSUPPORTED
;
274 Compute 8-bit checksum of a buffer.
276 @param ptr Pointer to buffer.
277 @param len Length of buffer in bytes.
279 @return 8-bit checksum of all bytes in buffer.
280 @return If ptr is NULL or len is zero, zero is returned.
296 if (ptr
== NULL
|| len
== 0) {
301 cksum
= (UINT8
) (cksum
+*bptr
++);
309 Test to see if this driver supports Controller. Any Controller
310 that contains a Nii protocol can be supported.
312 @param This Protocol instance pointer.
313 @param Controller Handle of device to test.
314 @param RemainingDevicePath Not used.
316 @retval EFI_SUCCESS This driver supports this device.
317 @retval EFI_ALREADY_STARTED This driver is already running on this device.
318 @retval other This driver does not support this device.
323 SimpleNetworkDriverSupported (
324 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
325 IN EFI_HANDLE Controller
,
326 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
330 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL
*NiiProtocol
;
335 Status
= gBS
->OpenProtocol (
337 &gEfiDevicePathProtocolGuid
,
339 This
->DriverBindingHandle
,
341 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
343 if (EFI_ERROR (Status
)) {
347 Status
= gBS
->OpenProtocol (
349 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
350 (VOID
**) &NiiProtocol
,
351 This
->DriverBindingHandle
,
353 EFI_OPEN_PROTOCOL_BY_DRIVER
355 if (Status
== EFI_ALREADY_STARTED
)
357 DEBUG ((EFI_D_INFO
, "Support(): Already Started. on handle %x\n", Controller
));
358 return EFI_ALREADY_STARTED
;
361 if (!EFI_ERROR (Status
))
363 DEBUG ((EFI_D_INFO
, "Support(): UNDI3.1 found on handle %x\n", Controller
));
367 // try the older 3.0 driver
369 Status
= gBS
->OpenProtocol (
371 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
372 (VOID
**) &NiiProtocol
,
373 This
->DriverBindingHandle
,
375 EFI_OPEN_PROTOCOL_BY_DRIVER
377 if (EFI_ERROR (Status
)) {
381 DEBUG ((EFI_D_INFO
, "Support(): UNDI3.0 found on handle %x\n", Controller
));
384 // check the version, we don't want to connect to the undi16
386 if (NiiProtocol
->Type
!= EfiNetworkInterfaceUndi
) {
387 Status
= EFI_UNSUPPORTED
;
391 // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.
393 if (NiiProtocol
->ID
& 0x0F) {
394 DEBUG ((EFI_D_NET
, "\n!PXE structure is not paragraph aligned.\n"));
395 Status
= EFI_UNSUPPORTED
;
399 pxe
= (PXE_UNDI
*) (UINTN
) (NiiProtocol
->ID
);
402 // Verify !PXE revisions.
404 if (pxe
->hw
.Signature
!= PXE_ROMID_SIGNATURE
) {
405 DEBUG ((EFI_D_NET
, "\n!PXE signature is not valid.\n"));
406 Status
= EFI_UNSUPPORTED
;
410 if (pxe
->hw
.Rev
< PXE_ROMID_REV
) {
411 DEBUG ((EFI_D_NET
, "\n!PXE.Rev is not supported.\n"));
412 Status
= EFI_UNSUPPORTED
;
416 if (pxe
->hw
.MajorVer
< PXE_ROMID_MAJORVER
) {
418 DEBUG ((EFI_D_NET
, "\n!PXE.MajorVer is not supported.\n"));
419 Status
= EFI_UNSUPPORTED
;
422 } else if (pxe
->hw
.MajorVer
== PXE_ROMID_MAJORVER
&& pxe
->hw
.MinorVer
< PXE_ROMID_MINORVER
) {
423 DEBUG ((EFI_D_NET
, "\n!PXE.MinorVer is not supported."));
424 Status
= EFI_UNSUPPORTED
;
428 // Do S/W UNDI specific checks.
430 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_HW_UNDI
) == 0) {
431 if (pxe
->sw
.EntryPoint
< pxe
->sw
.Len
) {
432 DEBUG ((EFI_D_NET
, "\n!PXE S/W entry point is not valid."));
433 Status
= EFI_UNSUPPORTED
;
437 if (pxe
->sw
.BusCnt
== 0) {
438 DEBUG ((EFI_D_NET
, "\n!PXE.BusCnt is zero."));
439 Status
= EFI_UNSUPPORTED
;
444 Status
= EFI_SUCCESS
;
445 DEBUG ((EFI_D_INFO
, "Support(): supported on %x\n", Controller
));
451 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
452 This
->DriverBindingHandle
,
459 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
460 This
->DriverBindingHandle
,
470 called for any handle that we said "supported" in the above call!
472 @param This Protocol instance pointer.
473 @param Controller Handle of device to start
474 @param RemainingDevicePath Not used.
476 @retval EFI_SUCCESS This driver supports this device.
477 @retval other This driver failed to start this device.
482 SimpleNetworkDriverStart (
483 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
484 IN EFI_HANDLE Controller
,
485 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
488 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL
*Nii
;
489 EFI_DEVICE_PATH_PROTOCOL
*NiiDevicePath
;
495 EFI_PHYSICAL_ADDRESS paddr
;
499 PXE_PCI_CONFIG_INFO ConfigInfo
;
500 PCI_TYPE00
*ConfigHeader
;
503 PXE_STATFLAGS InitStatFlags
;
505 DEBUG ((EFI_D_NET
, "\nSnpNotifyNetworkInterfaceIdentifier() "));
507 Status
= gBS
->OpenProtocol (
509 &gEfiDevicePathProtocolGuid
,
510 (VOID
**) &NiiDevicePath
,
511 This
->DriverBindingHandle
,
513 EFI_OPEN_PROTOCOL_BY_DRIVER
516 if (EFI_ERROR (Status
)) {
520 Status
= gBS
->LocateDevicePath (
521 &gEfiPciIoProtocolGuid
,
526 if (EFI_ERROR (Status
)) {
530 Status
= gBS
->OpenProtocol (
532 &gEfiPciIoProtocolGuid
,
533 (VOID
**) &mPciIoFncs
,
534 This
->DriverBindingHandle
,
536 EFI_OPEN_PROTOCOL_GET_PROTOCOL
538 if (EFI_ERROR (Status
)) {
542 // Get the NII interface. look for 3.1 undi first, if it is not there
543 // then look for 3.0, validate the interface.
545 Status
= gBS
->OpenProtocol (
547 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
549 This
->DriverBindingHandle
,
551 EFI_OPEN_PROTOCOL_BY_DRIVER
553 if (Status
== EFI_ALREADY_STARTED
) {
556 &gEfiDevicePathProtocolGuid
,
557 This
->DriverBindingHandle
,
563 if (!EFI_ERROR (Status
)) {
565 // probably not a 3.1 UNDI
568 DEBUG ((EFI_D_INFO
, "Start(): UNDI3.1 found\n"));
572 Status
= gBS
->OpenProtocol (
574 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
576 This
->DriverBindingHandle
,
578 EFI_OPEN_PROTOCOL_BY_DRIVER
580 if (EFI_ERROR (Status
)) {
583 &gEfiDevicePathProtocolGuid
,
584 This
->DriverBindingHandle
,
591 DEBUG ((EFI_D_INFO
, "Start(): UNDI3.0 found\n"));
594 pxe
= (PXE_UNDI
*) (UINTN
) (Nii
->ID
);
596 if (calc_8bit_cksum (pxe
, pxe
->hw
.Len
) != 0) {
597 DEBUG ((EFI_D_NET
, "\n!PXE checksum is not correct.\n"));
601 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
) != 0) {
603 // We can get any packets.
605 } else if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
) != 0) {
607 // We need to be able to get broadcast packets for DHCP.
608 // If we do not have promiscuous support, we must at least have
609 // broadcast support or we cannot do DHCP!
612 DEBUG ((EFI_D_NET
, "\nUNDI does not have promiscuous or broadcast support."));
616 // OK, we like this UNDI, and we know snp is not already there on this handle
617 // Allocate and initialize a new simple network protocol structure.
619 Status
= mPciIoFncs
->AllocateBuffer (
623 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
628 if (Status
!= EFI_SUCCESS
) {
629 DEBUG ((EFI_D_NET
, "\nCould not allocate SNP_DRIVER structure.\n"));
633 snp
= (SNP_DRIVER
*) (UINTN
) addr
;
636 Size
= SNP_MEM_PAGES (sizeof (SNP_DRIVER
));
638 Status
= mPciIoFncs
->Map (
640 EfiPciIoOperationBusMasterCommonBuffer
,
649 DEBUG ((EFI_D_NET
, "\nSNP_DRIVER @ %Xh, sizeof(SNP_DRIVER) == %d", addr
, sizeof (SNP_DRIVER
)));
650 snp
= (SNP_DRIVER
*) (UINTN
) paddr
;
651 snp
->SnpDriverUnmap
= addrUnmap
;
654 ZeroMem (snp
, sizeof (SNP_DRIVER
));
656 snp
->IoFncs
= mPciIoFncs
;
657 snp
->IsOldUndi
= (BOOLEAN
) (!UndiNew
);
659 snp
->Signature
= SNP_DRIVER_SIGNATURE
;
661 EfiInitializeLock (&snp
->lock
, TPL_NOTIFY
);
663 snp
->snp
.Revision
= EFI_SIMPLE_NETWORK_PROTOCOL_REVISION
;
664 snp
->snp
.Start
= snp_undi32_start
;
665 snp
->snp
.Stop
= snp_undi32_stop
;
666 snp
->snp
.Initialize
= snp_undi32_initialize
;
667 snp
->snp
.Reset
= snp_undi32_reset
;
668 snp
->snp
.Shutdown
= snp_undi32_shutdown
;
669 snp
->snp
.ReceiveFilters
= snp_undi32_receive_filters
;
670 snp
->snp
.StationAddress
= snp_undi32_station_address
;
671 snp
->snp
.Statistics
= snp_undi32_statistics
;
672 snp
->snp
.MCastIpToMac
= snp_undi32_mcast_ip_to_mac
;
673 snp
->snp
.NvData
= snp_undi32_nvdata
;
674 snp
->snp
.GetStatus
= snp_undi32_get_status
;
675 snp
->snp
.Transmit
= snp_undi32_transmit
;
676 snp
->snp
.Receive
= snp_undi32_receive
;
677 snp
->snp
.WaitForPacket
= NULL
;
679 snp
->snp
.Mode
= &snp
->mode
;
681 snp
->tx_rx_bufsize
= 0;
682 snp
->tx_rx_buffer
= NULL
;
684 snp
->if_num
= Nii
->IfNum
;
686 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_HW_UNDI
) != 0) {
687 snp
->is_swundi
= FALSE
;
688 snp
->issue_undi32_command
= &issue_hwundi_command
;
690 snp
->is_swundi
= TRUE
;
692 if ((pxe
->sw
.Implementation
& PXE_ROMID_IMP_SW_VIRT_ADDR
) != 0) {
693 snp
->issue_undi32_command
= (issue_undi32_command
) (UINTN
) pxe
->sw
.EntryPoint
;
695 snp
->issue_undi32_command
= (issue_undi32_command
) (UINTN
) ((UINT8
) (UINTN
) pxe
+ pxe
->sw
.EntryPoint
);
699 // Allocate a global CPB and DB buffer for this UNDI interface.
700 // we do this because:
702 // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be
703 // within 2GB limit, create them here and map them so that when undi calls
704 // v2p callback to check if the physical address is < 2gb, we will pass.
706 // -This is not a requirement for 3.1 or later UNDIs but the code looks
707 // simpler if we use the same cpb, db variables for both old and new undi
708 // interfaces from all the SNP interface calls (we don't map the buffers
709 // for the newer undi interfaces though)
711 // -it is OK to allocate one global set of CPB, DB pair for each UNDI
712 // interface as EFI does not multi-task and so SNP will not be re-entered!
714 Status
= mPciIoFncs
->AllocateBuffer (
718 SNP_MEM_PAGES (4096),
723 if (Status
!= EFI_SUCCESS
) {
724 DEBUG ((EFI_D_NET
, "\nCould not allocate CPB and DB structures.\n"));
725 goto Error_DeleteSNP
;
728 if (snp
->IsOldUndi
) {
729 Size
= SNP_MEM_PAGES (4096);
731 Status
= mPciIoFncs
->Map (
733 EfiPciIoOperationBusMasterCommonBuffer
,
742 snp
->cpb
= (VOID
*) (UINTN
) paddr
;
743 snp
->db
= (VOID
*) ((UINTN
) paddr
+ 2048);
745 snp
->cpb
= (VOID
*) (UINTN
) addr
;
746 snp
->db
= (VOID
*) ((UINTN
) addr
+ 2048);
749 // pxe_start call is going to give the callback functions to UNDI, these callback
750 // functions use the BarIndex values from the snp structure, so these must be initialized
751 // with default values before doing a pxe_start. The correct values can be obtained after
752 // getting the config information from UNDI
754 snp
->MemoryBarIndex
= 0;
758 // we need the undi init information many times in this snp code, just get it
759 // once here and store it in the snp driver structure. to get Init Info
760 // from UNDI we have to start undi first.
762 Status
= pxe_start (snp
);
764 if (Status
!= EFI_SUCCESS
) {
765 goto Error_DeleteCPBDB
;
768 snp
->cdb
.OpCode
= PXE_OPCODE_GET_INIT_INFO
;
769 snp
->cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
771 snp
->cdb
.CPBsize
= PXE_CPBSIZE_NOT_USED
;
772 snp
->cdb
.CPBaddr
= PXE_DBADDR_NOT_USED
;
774 snp
->cdb
.DBsize
= sizeof snp
->init_info
;
775 snp
->cdb
.DBaddr
= (UINT64
)(UINTN
) &snp
->init_info
;
777 snp
->cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
778 snp
->cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
780 snp
->cdb
.IFnum
= snp
->if_num
;
781 snp
->cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
783 DEBUG ((EFI_D_NET
, "\nsnp->undi.get_init_info() "));
785 (*snp
->issue_undi32_command
) ((UINT64
)(UINTN
) &snp
->cdb
);
788 // Save the INIT Stat Code...
790 InitStatFlags
= snp
->cdb
.StatFlags
;
792 if (snp
->cdb
.StatCode
!= PXE_STATCODE_SUCCESS
) {
793 DEBUG ((EFI_D_NET
, "\nsnp->undi.init_info() %xh:%xh\n", snp
->cdb
.StatFlags
, snp
->cdb
.StatCode
));
795 goto Error_DeleteCPBDB
;
798 snp
->cdb
.OpCode
= PXE_OPCODE_GET_CONFIG_INFO
;
799 snp
->cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
801 snp
->cdb
.CPBsize
= PXE_CPBSIZE_NOT_USED
;
802 snp
->cdb
.CPBaddr
= PXE_DBADDR_NOT_USED
;
804 snp
->cdb
.DBsize
= sizeof ConfigInfo
;
805 snp
->cdb
.DBaddr
= (UINT64
)(UINTN
) &ConfigInfo
;
807 snp
->cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
808 snp
->cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
810 snp
->cdb
.IFnum
= snp
->if_num
;
811 snp
->cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
813 DEBUG ((EFI_D_NET
, "\nsnp->undi.get_config_info() "));
815 (*snp
->issue_undi32_command
) ((UINT64
)(UINTN
) &snp
->cdb
);
817 if (snp
->cdb
.StatCode
!= PXE_STATCODE_SUCCESS
) {
818 DEBUG ((EFI_D_NET
, "\nsnp->undi.config_info() %xh:%xh\n", snp
->cdb
.StatFlags
, snp
->cdb
.StatCode
));
820 goto Error_DeleteCPBDB
;
823 // Find the correct BAR to do IO.
826 // Enumerate through the PCI BARs for the device to determine which one is
827 // the IO BAR. Save the index of the BAR into the adapter info structure.
828 // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped
830 ConfigHeader
= (PCI_TYPE00
*) &ConfigInfo
.Config
.Byte
[0];
831 TempBar
= (UINT32
*) &ConfigHeader
->Device
.Bar
[0];
832 for (BarIndex
= 0; BarIndex
<= 5; BarIndex
++) {
833 if ((*TempBar
& PCI_BAR_MEM_MASK
) == PCI_BAR_MEM_64BIT
) {
835 // This is a 64-bit memory bar, skip this and the
841 if ((*TempBar
& PCI_BAR_IO_MASK
) == PCI_BAR_IO_MODE
) {
842 snp
->IoBarIndex
= BarIndex
;
850 // We allocate 2 more global buffers for undi 3.0 interface. We use these
851 // buffers to pass to undi when the user buffers are beyond 4GB.
852 // UNDI 3.0 wants all the addresses passed to it to be
853 // within 2GB limit, create them here and map them so that when undi calls
854 // v2p callback to check if the physical address is < 2gb, we will pass.
856 // For 3.1 and later UNDIs, we do not do this because undi is
857 // going to call the map() callback if and only if it wants to use the
858 // device address for any address it receives.
860 if (snp
->IsOldUndi
) {
862 // buffer for receive
864 Size
= SNP_MEM_PAGES (snp
->init_info
.MediaHeaderLen
+ snp
->init_info
.FrameDataLen
);
865 Status
= mPciIoFncs
->AllocateBuffer (
874 if (Status
!= EFI_SUCCESS
) {
875 DEBUG ((EFI_D_ERROR
, "\nCould not allocate receive buffer.\n"));
876 goto Error_DeleteCPBDB
;
879 Status
= mPciIoFncs
->Map (
881 EfiPciIoOperationBusMasterCommonBuffer
,
885 &snp
->ReceiveBufUnmap
890 snp
->receive_buf
= (UINT8
*) (UINTN
) paddr
;
893 // buffer for fill_header
895 Size
= SNP_MEM_PAGES (snp
->init_info
.MediaHeaderLen
);
896 Status
= mPciIoFncs
->AllocateBuffer (
905 if (Status
!= EFI_SUCCESS
) {
906 DEBUG ((EFI_D_ERROR
, "\nCould not allocate fill_header buffer.\n"));
907 goto Error_DeleteRCVBuf
;
910 Status
= mPciIoFncs
->Map (
912 EfiPciIoOperationBusMasterCommonBuffer
,
916 &snp
->FillHdrBufUnmap
920 snp
->fill_hdr_buf
= (UINT8
*) (UINTN
) paddr
;
923 // Initialize simple network protocol mode structure
925 snp
->mode
.State
= EfiSimpleNetworkStopped
;
926 snp
->mode
.HwAddressSize
= snp
->init_info
.HWaddrLen
;
927 snp
->mode
.MediaHeaderSize
= snp
->init_info
.MediaHeaderLen
;
928 snp
->mode
.MaxPacketSize
= snp
->init_info
.FrameDataLen
;
929 snp
->mode
.NvRamAccessSize
= snp
->init_info
.NvWidth
;
930 snp
->mode
.NvRamSize
= snp
->init_info
.NvCount
* snp
->mode
.NvRamAccessSize
;
931 snp
->mode
.IfType
= snp
->init_info
.IFtype
;
932 snp
->mode
.MaxMCastFilterCount
= snp
->init_info
.MCastFilterCnt
;
933 snp
->mode
.MCastFilterCount
= 0;
935 switch (InitStatFlags
& PXE_STATFLAGS_CABLE_DETECT_MASK
) {
936 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED
:
937 snp
->mode
.MediaPresentSupported
= TRUE
;
940 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED
:
942 snp
->mode
.MediaPresentSupported
= FALSE
;
945 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_STATION_ADDR_SETTABLE
) != 0) {
946 snp
->mode
.MacAddressChangeable
= TRUE
;
948 snp
->mode
.MacAddressChangeable
= FALSE
;
951 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED
) != 0) {
952 snp
->mode
.MultipleTxSupported
= TRUE
;
954 snp
->mode
.MultipleTxSupported
= FALSE
;
957 snp
->mode
.ReceiveFilterMask
= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
959 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
) != 0) {
960 snp
->mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
964 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
) != 0) {
965 snp
->mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
969 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
) != 0) {
970 snp
->mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
974 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED
) != 0) {
975 snp
->mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
979 if (pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
) {
980 snp
->mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
984 snp
->mode
.ReceiveFilterSetting
= 0;
987 // need to get the station address to save in the mode structure. we need to
988 // initialize the UNDI first for this.
990 snp
->tx_rx_bufsize
= snp
->init_info
.MemoryRequired
;
991 Status
= pxe_init (snp
, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE
);
995 goto Error_DeleteHdrBuf
;
998 Status
= pxe_get_stn_addr (snp
);
1000 if (Status
!= EFI_SUCCESS
) {
1001 DEBUG ((EFI_D_ERROR
, "\nsnp->undi.get_station_addr() failed.\n"));
1004 goto Error_DeleteHdrBuf
;
1007 snp
->mode
.MediaPresent
= FALSE
;
1010 // We should not leave UNDI started and initialized here. this DriverStart()
1011 // routine must only find and attach the SNP interface to UNDI layer that it
1012 // finds on the given handle!
1013 // The UNDI layer will be started when upper layers call snp->start.
1014 // How ever, this DriverStart() must fill up the snp mode structure which
1015 // contains the MAC address of the NIC. For this reason we started and
1016 // initialized UNDI here, now we are done, do a shutdown and stop of the
1023 // add SNP to the undi handle
1025 Status
= gBS
->InstallProtocolInterface (
1027 &gEfiSimpleNetworkProtocolGuid
,
1028 EFI_NATIVE_INTERFACE
,
1032 if (!EFI_ERROR (Status
)) {
1037 if (snp
->IsOldUndi
) {
1038 Status
= mPciIoFncs
->Unmap (
1040 snp
->FillHdrBufUnmap
1042 Size
= SNP_MEM_PAGES (snp
->init_info
.MediaHeaderLen
);
1043 mPciIoFncs
->FreeBuffer (
1051 if (snp
->IsOldUndi
) {
1052 Status
= mPciIoFncs
->Unmap (
1054 snp
->ReceiveBufUnmap
1056 Size
= SNP_MEM_PAGES (snp
->init_info
.MediaHeaderLen
+ snp
->init_info
.FrameDataLen
);
1057 mPciIoFncs
->FreeBuffer (
1066 if (snp
->IsOldUndi
) {
1067 Status
= mPciIoFncs
->Unmap (
1073 Status
= mPciIoFncs
->FreeBuffer (
1075 SNP_MEM_PAGES (4096),
1080 if (snp
->IsOldUndi
) {
1081 Status
= mPciIoFncs
->Unmap (
1087 mPciIoFncs
->FreeBuffer (
1089 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
1094 gBS
->CloseProtocol (
1096 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
1097 This
->DriverBindingHandle
,
1101 gBS
->CloseProtocol (
1103 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
1104 This
->DriverBindingHandle
,
1109 gBS
->CloseProtocol (
1111 &gEfiDevicePathProtocolGuid
,
1112 This
->DriverBindingHandle
,
1127 SimpleNetworkDriverStop (
1128 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1129 IN EFI_HANDLE Controller
,
1130 IN UINTN NumberOfChildren
,
1131 IN EFI_HANDLE
*ChildHandleBuffer
1135 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpProtocol
;
1139 // Get our context back.
1141 Status
= gBS
->OpenProtocol (
1143 &gEfiSimpleNetworkProtocolGuid
,
1144 (VOID
**) &SnpProtocol
,
1145 This
->DriverBindingHandle
,
1147 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1150 if (EFI_ERROR (Status
)) {
1151 return EFI_UNSUPPORTED
;
1154 Snp
= EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol
);
1156 Status
= gBS
->UninstallProtocolInterface (
1158 &gEfiSimpleNetworkProtocolGuid
,
1162 if (EFI_ERROR (Status
)) {
1166 if (!Snp
->IsOldUndi
) {
1167 Status
= gBS
->CloseProtocol (
1169 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
1170 This
->DriverBindingHandle
,
1174 Status
= gBS
->CloseProtocol (
1176 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
1177 This
->DriverBindingHandle
,
1182 Status
= gBS
->CloseProtocol (
1184 &gEfiDevicePathProtocolGuid
,
1185 This
->DriverBindingHandle
,
1192 if (Snp
->IsOldUndi
) {
1193 Status
= mPciIoFncs
->Unmap (
1195 Snp
->FillHdrBufUnmap
1198 mPciIoFncs
->FreeBuffer (
1200 SNP_MEM_PAGES (Snp
->init_info
.MediaHeaderLen
),
1203 Status
= mPciIoFncs
->Unmap (
1205 Snp
->ReceiveBufUnmap
1208 mPciIoFncs
->FreeBuffer (
1210 SNP_MEM_PAGES (Snp
->init_info
.MediaHeaderLen
+ Snp
->init_info
.FrameDataLen
),
1214 Status
= mPciIoFncs
->Unmap (
1218 Status
= mPciIoFncs
->Unmap (
1224 mPciIoFncs
->FreeBuffer (
1226 SNP_MEM_PAGES (4096),
1230 mPciIoFncs
->FreeBuffer (
1232 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
1241 Install all the driver protocol
1243 @param entry EFI_IMAGE_ENTRY_POINT)
1245 @retval EFI_SUCEESS Initialization routine has found UNDI hardware,
1246 loaded it's ROM, and installed a notify event for
1247 the Network Indentifier Interface Protocol
1249 @retval Other Return value from HandleProtocol for
1250 DeviceIoProtocol or LoadedImageProtocol
1255 InitializeSnpNiiDriver (
1256 IN EFI_HANDLE ImageHandle
,
1257 IN EFI_SYSTEM_TABLE
*SystemTable
1260 return EfiLibInstallDriverBindingComponentName2 (
1263 &mSimpleNetworkDriverBinding
,
1265 &gSimpleNetworkComponentName
,
1266 &gSimpleNetworkComponentName2