2 Copyright (c) 2006, 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.
22 // Module global variables needed to support undi 3.0 interface
24 EFI_PCI_IO_PROTOCOL
*mPciIoFncs
;
25 struct s_v2p
*_v2p
= NULL
; // undi3.0 map_list head
26 // End Global variables
31 issue_hwundi_command (
45 Aprint ("\nissue_hwundi_command() - This should not be called!");
49 return EFI_INVALID_PARAMETER
;
53 // %%TBD - For now, nothing is done.
55 return EFI_UNSUPPORTED
;
67 Compute 8-bit checksum of a buffer.
70 ptr - Pointer to buffer.
71 len - Length of buffer in bytes.
74 8-bit checksum of all bytes in buffer.
75 If ptr is NULL or len is zero, zero is returned.
85 if (ptr
== NULL
|| len
== 0) {
90 cksum
= (UINT8
) (cksum
+*bptr
++);
99 SimpleNetworkDriverSupported (
100 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
101 IN EFI_HANDLE Controller
,
102 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
107 Test to see if this driver supports Controller. Any Controller
108 that contains a Nii protocol can be supported.
111 This - Protocol instance pointer.
112 Controller - Handle of device to test.
113 RemainingDevicePath - Not used.
116 EFI_SUCCESS - This driver supports this device.
117 EFI_ALREADY_STARTED - This driver is already running on this device.
118 other - This driver does not support this device.
123 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL
*NiiProtocol
;
128 Status
= gBS
->OpenProtocol (
130 &gEfiDevicePathProtocolGuid
,
132 This
->DriverBindingHandle
,
134 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
136 if (EFI_ERROR (Status
)) {
140 Status
= gBS
->OpenProtocol (
142 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
143 (VOID
**) &NiiProtocol
,
144 This
->DriverBindingHandle
,
146 EFI_OPEN_PROTOCOL_BY_DRIVER
148 if (Status
== EFI_ALREADY_STARTED
)
151 Aprint ("Support(): Already Started. on handle %x\n", Controller
);
153 return EFI_ALREADY_STARTED
;
156 if (!EFI_ERROR (Status
))
160 Aprint ("Support(): UNDI3.1 found on handle %x\n", Controller
);
166 // try the older 3.0 driver
168 Status
= gBS
->OpenProtocol (
170 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
171 (VOID
**) &NiiProtocol
,
172 This
->DriverBindingHandle
,
174 EFI_OPEN_PROTOCOL_BY_DRIVER
176 if (EFI_ERROR (Status
)) {
181 Aprint ("Support(): UNDI3.0 found on handle %x\n", Controller
);
186 // check the version, we don't want to connect to the undi16
188 if (NiiProtocol
->Type
!= EfiNetworkInterfaceUndi
) {
189 Status
= EFI_UNSUPPORTED
;
193 // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.
195 if (NiiProtocol
->ID
& 0x0F) {
196 DEBUG ((EFI_D_NET
, "\n!PXE structure is not paragraph aligned.\n"));
197 Status
= EFI_UNSUPPORTED
;
201 pxe
= (PXE_UNDI
*) (UINTN
) (NiiProtocol
->ID
);
204 // Verify !PXE revisions.
206 if (pxe
->hw
.Signature
!= PXE_ROMID_SIGNATURE
) {
207 DEBUG ((EFI_D_NET
, "\n!PXE signature is not valid.\n"));
208 Status
= EFI_UNSUPPORTED
;
212 if (pxe
->hw
.Rev
< PXE_ROMID_REV
) {
213 DEBUG ((EFI_D_NET
, "\n!PXE.Rev is not supported.\n"));
214 Status
= EFI_UNSUPPORTED
;
218 if (pxe
->hw
.MajorVer
< PXE_ROMID_MAJORVER
) {
220 DEBUG ((EFI_D_NET
, "\n!PXE.MajorVer is not supported.\n"));
221 Status
= EFI_UNSUPPORTED
;
224 } else if (pxe
->hw
.MajorVer
== PXE_ROMID_MAJORVER
&& pxe
->hw
.MinorVer
< PXE_ROMID_MINORVER
) {
225 DEBUG ((EFI_D_NET
, "\n!PXE.MinorVer is not supported."));
226 Status
= EFI_UNSUPPORTED
;
230 // Do S/W UNDI specific checks.
232 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_HW_UNDI
) == 0) {
233 if (pxe
->sw
.EntryPoint
< pxe
->sw
.Len
) {
234 DEBUG ((EFI_D_NET
, "\n!PXE S/W entry point is not valid."));
235 Status
= EFI_UNSUPPORTED
;
239 if (pxe
->sw
.BusCnt
== 0) {
240 DEBUG ((EFI_D_NET
, "\n!PXE.BusCnt is zero."));
241 Status
= EFI_UNSUPPORTED
;
246 Status
= EFI_SUCCESS
;
248 Aprint ("Support(): supported on %x\n", Controller
);
256 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
257 This
->DriverBindingHandle
,
264 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
265 This
->DriverBindingHandle
,
276 SimpleNetworkDriverStart (
277 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
278 IN EFI_HANDLE Controller
,
279 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
284 called for any handle that we said "supported" in the above call!
287 This - Protocol instance pointer.
288 Controller - Handle of device to start
289 RemainingDevicePath - Not used.
292 EFI_SUCCESS - This driver supports this device.
293 other - This driver failed to start this device.
297 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL
*Nii
;
298 EFI_DEVICE_PATH_PROTOCOL
*NiiDevicePath
;
304 EFI_PHYSICAL_ADDRESS paddr
;
308 PXE_PCI_CONFIG_INFO ConfigInfo
;
309 PCI_TYPE00
*ConfigHeader
;
312 PXE_STATFLAGS InitStatFlags
;
314 DEBUG ((EFI_D_NET
, "\nSnpNotifyNetworkInterfaceIdentifier() "));
316 Status
= gBS
->OpenProtocol (
318 &gEfiDevicePathProtocolGuid
,
319 (VOID
**) &NiiDevicePath
,
320 This
->DriverBindingHandle
,
322 EFI_OPEN_PROTOCOL_BY_DRIVER
325 if (EFI_ERROR (Status
)) {
329 Status
= gBS
->LocateDevicePath (
330 &gEfiPciIoProtocolGuid
,
335 if (EFI_ERROR (Status
)) {
339 Status
= gBS
->OpenProtocol (
341 &gEfiPciIoProtocolGuid
,
342 (VOID
**) &mPciIoFncs
,
343 This
->DriverBindingHandle
,
345 EFI_OPEN_PROTOCOL_GET_PROTOCOL
347 if (EFI_ERROR (Status
)) {
351 // Get the NII interface. look for 3.1 undi first, if it is not there
352 // then look for 3.0, validate the interface.
354 Status
= gBS
->OpenProtocol (
356 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
358 This
->DriverBindingHandle
,
360 EFI_OPEN_PROTOCOL_BY_DRIVER
362 if (Status
== EFI_ALREADY_STARTED
) {
365 &gEfiDevicePathProtocolGuid
,
366 This
->DriverBindingHandle
,
372 if (!EFI_ERROR (Status
)) {
374 // probably not a 3.1 UNDI
378 Aprint ("Start(): UNDI3.1 found\n");
383 Status
= gBS
->OpenProtocol (
385 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
387 This
->DriverBindingHandle
,
389 EFI_OPEN_PROTOCOL_BY_DRIVER
391 if (EFI_ERROR (Status
)) {
394 &gEfiDevicePathProtocolGuid
,
395 This
->DriverBindingHandle
,
403 Aprint ("Start(): UNDI3.0 found\n");
408 pxe
= (PXE_UNDI
*) (UINTN
) (Nii
->ID
);
410 if (calc_8bit_cksum (pxe
, pxe
->hw
.Len
) != 0) {
411 DEBUG ((EFI_D_NET
, "\n!PXE checksum is not correct.\n"));
415 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
) != 0) {
417 // We can get any packets.
419 } else if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
) != 0) {
421 // We need to be able to get broadcast packets for DHCP.
422 // If we do not have promiscuous support, we must at least have
423 // broadcast support or we cannot do DHCP!
426 DEBUG ((EFI_D_NET
, "\nUNDI does not have promiscuous or broadcast support."));
430 // OK, we like this UNDI, and we know snp is not already there on this handle
431 // Allocate and initialize a new simple network protocol structure.
433 Status
= mPciIoFncs
->AllocateBuffer (
437 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
442 if (Status
!= EFI_SUCCESS
) {
443 DEBUG ((EFI_D_NET
, "\nCould not allocate SNP_DRIVER structure.\n"));
447 snp
= (SNP_DRIVER
*) (UINTN
) addr
;
450 Size
= SNP_MEM_PAGES (sizeof (SNP_DRIVER
));
452 Status
= mPciIoFncs
->Map (
454 EfiPciIoOperationBusMasterCommonBuffer
,
463 DEBUG ((EFI_D_NET
, "\nSNP_DRIVER @ %Xh, sizeof(SNP_DRIVER) == %d", addr
, sizeof (SNP_DRIVER
)));
464 snp
= (SNP_DRIVER
*) (UINTN
) paddr
;
465 snp
->SnpDriverUnmap
= addrUnmap
;
468 ZeroMem (snp
, sizeof (SNP_DRIVER
));
470 snp
->IoFncs
= mPciIoFncs
;
471 snp
->IsOldUndi
= (BOOLEAN
) (!UndiNew
);
473 snp
->Signature
= SNP_DRIVER_SIGNATURE
;
475 EfiInitializeLock (&snp
->lock
, EFI_TPL_NOTIFY
);
477 snp
->snp
.Revision
= EFI_SIMPLE_NETWORK_PROTOCOL_REVISION
;
478 snp
->snp
.Start
= snp_undi32_start
;
479 snp
->snp
.Stop
= snp_undi32_stop
;
480 snp
->snp
.Initialize
= snp_undi32_initialize
;
481 snp
->snp
.Reset
= snp_undi32_reset
;
482 snp
->snp
.Shutdown
= snp_undi32_shutdown
;
483 snp
->snp
.ReceiveFilters
= snp_undi32_receive_filters
;
484 snp
->snp
.StationAddress
= snp_undi32_station_address
;
485 snp
->snp
.Statistics
= snp_undi32_statistics
;
486 snp
->snp
.MCastIpToMac
= snp_undi32_mcast_ip_to_mac
;
487 snp
->snp
.NvData
= snp_undi32_nvdata
;
488 snp
->snp
.GetStatus
= snp_undi32_get_status
;
489 snp
->snp
.Transmit
= snp_undi32_transmit
;
490 snp
->snp
.Receive
= snp_undi32_receive
;
491 snp
->snp
.WaitForPacket
= NULL
;
493 snp
->snp
.Mode
= &snp
->mode
;
495 snp
->tx_rx_bufsize
= 0;
496 snp
->tx_rx_buffer
= NULL
;
498 snp
->if_num
= Nii
->IfNum
;
500 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_HW_UNDI
) != 0) {
501 snp
->is_swundi
= FALSE
;
502 snp
->issue_undi32_command
= &issue_hwundi_command
;
504 snp
->is_swundi
= TRUE
;
506 if ((pxe
->sw
.Implementation
& PXE_ROMID_IMP_SW_VIRT_ADDR
) != 0) {
507 snp
->issue_undi32_command
= (issue_undi32_command
) (UINTN
) pxe
->sw
.EntryPoint
;
509 snp
->issue_undi32_command
= (issue_undi32_command
) (UINTN
) ((UINT8
) (UINTN
) pxe
+ pxe
->sw
.EntryPoint
);
513 // Allocate a global CPB and DB buffer for this UNDI interface.
514 // we do this because:
516 // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be
517 // within 2GB limit, create them here and map them so that when undi calls
518 // v2p callback to check if the physical address is < 2gb, we will pass.
520 // -This is not a requirement for 3.1 or later UNDIs but the code looks
521 // simpler if we use the same cpb, db variables for both old and new undi
522 // interfaces from all the SNP interface calls (we don't map the buffers
523 // for the newer undi interfaces though)
525 // -it is OK to allocate one global set of CPB, DB pair for each UNDI
526 // interface as EFI does not multi-task and so SNP will not be re-entered!
528 Status
= mPciIoFncs
->AllocateBuffer (
532 SNP_MEM_PAGES (4096),
537 if (Status
!= EFI_SUCCESS
) {
538 DEBUG ((EFI_D_NET
, "\nCould not allocate CPB and DB structures.\n"));
539 goto Error_DeleteSNP
;
542 if (snp
->IsOldUndi
) {
543 Size
= SNP_MEM_PAGES (4096);
545 Status
= mPciIoFncs
->Map (
547 EfiPciIoOperationBusMasterCommonBuffer
,
556 snp
->cpb
= (VOID
*) (UINTN
) paddr
;
557 snp
->db
= (VOID
*) ((UINTN
) paddr
+ 2048);
559 snp
->cpb
= (VOID
*) (UINTN
) addr
;
560 snp
->db
= (VOID
*) ((UINTN
) addr
+ 2048);
563 // pxe_start call is going to give the callback functions to UNDI, these callback
564 // functions use the BarIndex values from the snp structure, so these must be initialized
565 // with default values before doing a pxe_start. The correct values can be obtained after
566 // getting the config information from UNDI
568 snp
->MemoryBarIndex
= 0;
572 // we need the undi init information many times in this snp code, just get it
573 // once here and store it in the snp driver structure. to get Init Info
574 // from UNDI we have to start undi first.
576 Status
= pxe_start (snp
);
578 if (Status
!= EFI_SUCCESS
) {
579 goto Error_DeleteCPBDB
;
582 snp
->cdb
.OpCode
= PXE_OPCODE_GET_INIT_INFO
;
583 snp
->cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
585 snp
->cdb
.CPBsize
= PXE_CPBSIZE_NOT_USED
;
586 snp
->cdb
.CPBaddr
= PXE_DBADDR_NOT_USED
;
588 snp
->cdb
.DBsize
= sizeof snp
->init_info
;
589 snp
->cdb
.DBaddr
= (UINT64
) (UINTN
) &snp
->init_info
;
591 snp
->cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
592 snp
->cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
594 snp
->cdb
.IFnum
= snp
->if_num
;
595 snp
->cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
597 DEBUG ((EFI_D_NET
, "\nsnp->undi.get_init_info() "));
599 (*snp
->issue_undi32_command
) ((UINT64
) (UINTN
) &snp
->cdb
);
602 // Save the INIT Stat Code...
604 InitStatFlags
= snp
->cdb
.StatFlags
;
606 if (snp
->cdb
.StatCode
!= PXE_STATCODE_SUCCESS
) {
607 DEBUG ((EFI_D_NET
, "\nsnp->undi.init_info() %xh:%xh\n", snp
->cdb
.StatFlags
, snp
->cdb
.StatCode
));
609 goto Error_DeleteCPBDB
;
612 snp
->cdb
.OpCode
= PXE_OPCODE_GET_CONFIG_INFO
;
613 snp
->cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
615 snp
->cdb
.CPBsize
= PXE_CPBSIZE_NOT_USED
;
616 snp
->cdb
.CPBaddr
= PXE_DBADDR_NOT_USED
;
618 snp
->cdb
.DBsize
= sizeof ConfigInfo
;
619 snp
->cdb
.DBaddr
= (UINT64
) (UINTN
) &ConfigInfo
;
621 snp
->cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
622 snp
->cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
624 snp
->cdb
.IFnum
= snp
->if_num
;
625 snp
->cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
627 DEBUG ((EFI_D_NET
, "\nsnp->undi.get_config_info() "));
629 (*snp
->issue_undi32_command
) ((UINT64
) (UINTN
) &snp
->cdb
);
631 if (snp
->cdb
.StatCode
!= PXE_STATCODE_SUCCESS
) {
632 DEBUG ((EFI_D_NET
, "\nsnp->undi.config_info() %xh:%xh\n", snp
->cdb
.StatFlags
, snp
->cdb
.StatCode
));
634 goto Error_DeleteCPBDB
;
637 // Find the correct BAR to do IO.
640 // Enumerate through the PCI BARs for the device to determine which one is
641 // the IO BAR. Save the index of the BAR into the adapter info structure.
642 // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped
644 ConfigHeader
= (PCI_TYPE00
*) &ConfigInfo
.Config
.Byte
[0];
645 TempBar
= (UINT32
*) &ConfigHeader
->Device
.Bar
[0];
646 for (BarIndex
= 0; BarIndex
<= 5; BarIndex
++) {
647 if ((*TempBar
& PCI_BAR_MEM_MASK
) == PCI_BAR_MEM_64BIT
) {
649 // This is a 64-bit memory bar, skip this and the
655 if ((*TempBar
& PCI_BAR_IO_MASK
) == PCI_BAR_IO_MODE
) {
656 snp
->IoBarIndex
= BarIndex
;
664 // We allocate 2 more global buffers for undi 3.0 interface. We use these
665 // buffers to pass to undi when the user buffers are beyond 4GB.
666 // UNDI 3.0 wants all the addresses passed to it to be
667 // within 2GB limit, create them here and map them so that when undi calls
668 // v2p callback to check if the physical address is < 2gb, we will pass.
670 // For 3.1 and later UNDIs, we do not do this because undi is
671 // going to call the map() callback if and only if it wants to use the
672 // device address for any address it receives.
674 if (snp
->IsOldUndi
) {
676 // buffer for receive
678 Size
= SNP_MEM_PAGES (snp
->init_info
.MediaHeaderLen
+ snp
->init_info
.FrameDataLen
);
679 Status
= mPciIoFncs
->AllocateBuffer (
688 if (Status
!= EFI_SUCCESS
) {
689 DEBUG ((EFI_D_ERROR
, "\nCould not allocate receive buffer.\n"));
690 goto Error_DeleteCPBDB
;
693 Status
= mPciIoFncs
->Map (
695 EfiPciIoOperationBusMasterCommonBuffer
,
699 &snp
->ReceiveBufUnmap
704 snp
->receive_buf
= (UINT8
*) (UINTN
) paddr
;
707 // buffer for fill_header
709 Size
= SNP_MEM_PAGES (snp
->init_info
.MediaHeaderLen
);
710 Status
= mPciIoFncs
->AllocateBuffer (
719 if (Status
!= EFI_SUCCESS
) {
720 DEBUG ((EFI_D_ERROR
, "\nCould not allocate fill_header buffer.\n"));
721 goto Error_DeleteRCVBuf
;
724 Status
= mPciIoFncs
->Map (
726 EfiPciIoOperationBusMasterCommonBuffer
,
730 &snp
->FillHdrBufUnmap
734 snp
->fill_hdr_buf
= (UINT8
*) (UINTN
) paddr
;
737 // Initialize simple network protocol mode structure
739 snp
->mode
.State
= EfiSimpleNetworkStopped
;
740 snp
->mode
.HwAddressSize
= snp
->init_info
.HWaddrLen
;
741 snp
->mode
.MediaHeaderSize
= snp
->init_info
.MediaHeaderLen
;
742 snp
->mode
.MaxPacketSize
= snp
->init_info
.FrameDataLen
;
743 snp
->mode
.NvRamAccessSize
= snp
->init_info
.NvWidth
;
744 snp
->mode
.NvRamSize
= snp
->init_info
.NvCount
* snp
->mode
.NvRamAccessSize
;
745 snp
->mode
.IfType
= snp
->init_info
.IFtype
;
746 snp
->mode
.MaxMCastFilterCount
= snp
->init_info
.MCastFilterCnt
;
747 snp
->mode
.MCastFilterCount
= 0;
749 switch (InitStatFlags
& PXE_STATFLAGS_CABLE_DETECT_MASK
) {
750 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED
:
751 snp
->mode
.MediaPresentSupported
= TRUE
;
754 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED
:
756 snp
->mode
.MediaPresentSupported
= FALSE
;
759 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_STATION_ADDR_SETTABLE
) != 0) {
760 snp
->mode
.MacAddressChangeable
= TRUE
;
762 snp
->mode
.MacAddressChangeable
= FALSE
;
765 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED
) != 0) {
766 snp
->mode
.MultipleTxSupported
= TRUE
;
768 snp
->mode
.MultipleTxSupported
= FALSE
;
771 snp
->mode
.ReceiveFilterMask
= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
773 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
) != 0) {
774 snp
->mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
778 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
) != 0) {
779 snp
->mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
783 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
) != 0) {
784 snp
->mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
788 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED
) != 0) {
789 snp
->mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
793 if (pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
) {
794 snp
->mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
798 snp
->mode
.ReceiveFilterSetting
= 0;
801 // need to get the station address to save in the mode structure. we need to
802 // initialize the UNDI first for this.
804 snp
->tx_rx_bufsize
= snp
->init_info
.MemoryRequired
;
805 Status
= pxe_init (snp
, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE
);
809 goto Error_DeleteHdrBuf
;
812 Status
= pxe_get_stn_addr (snp
);
814 if (Status
!= EFI_SUCCESS
) {
815 DEBUG ((EFI_D_ERROR
, "\nsnp->undi.get_station_addr() failed.\n"));
818 goto Error_DeleteHdrBuf
;
821 snp
->mode
.MediaPresent
= FALSE
;
824 // We should not leave UNDI started and initialized here. this DriverStart()
825 // routine must only find and attach the SNP interface to UNDI layer that it
826 // finds on the given handle!
827 // The UNDI layer will be started when upper layers call snp->start.
828 // How ever, this DriverStart() must fill up the snp mode structure which
829 // contains the MAC address of the NIC. For this reason we started and
830 // initialized UNDI here, now we are done, do a shutdown and stop of the
837 // add SNP to the undi handle
839 Status
= gBS
->InstallProtocolInterface (
841 &gEfiSimpleNetworkProtocolGuid
,
842 EFI_NATIVE_INTERFACE
,
846 if (!EFI_ERROR (Status
)) {
851 if (snp
->IsOldUndi
) {
852 Status
= mPciIoFncs
->Unmap (
856 Size
= SNP_MEM_PAGES (snp
->init_info
.MediaHeaderLen
);
857 mPciIoFncs
->FreeBuffer (
865 if (snp
->IsOldUndi
) {
866 Status
= mPciIoFncs
->Unmap (
870 Size
= SNP_MEM_PAGES (snp
->init_info
.MediaHeaderLen
+ snp
->init_info
.FrameDataLen
);
871 mPciIoFncs
->FreeBuffer (
880 if (snp
->IsOldUndi
) {
881 Status
= mPciIoFncs
->Unmap (
887 Status
= mPciIoFncs
->FreeBuffer (
889 SNP_MEM_PAGES (4096),
894 if (snp
->IsOldUndi
) {
895 Status
= mPciIoFncs
->Unmap (
901 mPciIoFncs
->FreeBuffer (
903 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
910 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
911 This
->DriverBindingHandle
,
917 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
918 This
->DriverBindingHandle
,
925 &gEfiDevicePathProtocolGuid
,
926 This
->DriverBindingHandle
,
936 SimpleNetworkDriverStop (
937 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
938 IN EFI_HANDLE Controller
,
939 IN UINTN NumberOfChildren
,
940 IN EFI_HANDLE
*ChildHandleBuffer
953 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpProtocol
;
957 // Get our context back.
959 Status
= gBS
->OpenProtocol (
961 &gEfiSimpleNetworkProtocolGuid
,
962 (VOID
**) &SnpProtocol
,
963 This
->DriverBindingHandle
,
965 EFI_OPEN_PROTOCOL_GET_PROTOCOL
968 if (EFI_ERROR (Status
)) {
969 return EFI_UNSUPPORTED
;
972 Snp
= EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol
);
974 Status
= gBS
->UninstallProtocolInterface (
976 &gEfiSimpleNetworkProtocolGuid
,
980 if (EFI_ERROR (Status
)) {
984 if (!Snp
->IsOldUndi
) {
985 Status
= gBS
->CloseProtocol (
987 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
988 This
->DriverBindingHandle
,
992 Status
= gBS
->CloseProtocol (
994 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
995 This
->DriverBindingHandle
,
1000 Status
= gBS
->CloseProtocol (
1002 &gEfiDevicePathProtocolGuid
,
1003 This
->DriverBindingHandle
,
1010 if (Snp
->IsOldUndi
) {
1011 Status
= mPciIoFncs
->Unmap (
1013 Snp
->FillHdrBufUnmap
1016 mPciIoFncs
->FreeBuffer (
1018 SNP_MEM_PAGES (Snp
->init_info
.MediaHeaderLen
),
1021 Status
= mPciIoFncs
->Unmap (
1023 Snp
->ReceiveBufUnmap
1026 mPciIoFncs
->FreeBuffer (
1028 SNP_MEM_PAGES (Snp
->init_info
.MediaHeaderLen
+ Snp
->init_info
.FrameDataLen
),
1032 Status
= mPciIoFncs
->Unmap (
1036 Status
= mPciIoFncs
->Unmap (
1042 mPciIoFncs
->FreeBuffer (
1044 SNP_MEM_PAGES (4096),
1048 mPciIoFncs
->FreeBuffer (
1050 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
1058 // Simple Network Protocol Driver Global Variables
1060 EFI_DRIVER_BINDING_PROTOCOL mSimpleNetworkDriverBinding
= {
1061 SimpleNetworkDriverSupported
,
1062 SimpleNetworkDriverStart
,
1063 SimpleNetworkDriverStop
,
1071 IN OUT
struct s_v2p
**v2p
,
1072 EFI_PCI_IO_PROTOCOL_OPERATION type
,
1078 Routine Description:
1079 This routine maps the given CPU address to a Device address. It creates a
1080 an entry in the map list with the virtual and physical addresses and the
1084 v2p - pointer to return a map list node pointer.
1085 type - the direction in which the data flows from the given virtual address
1086 device->cpu or cpu->device or both ways.
1087 vaddr - virtual address (or CPU address) to be mapped
1088 bsize - size of the buffer to be mapped.
1092 EFI_SUCEESS - routine has completed the mapping
1093 other - error as indicated.
1099 if ((v2p
== NULL
) || (vaddr
== NULL
) || (bsize
== 0)) {
1100 return EFI_INVALID_PARAMETER
;
1103 Status
= gBS
->AllocatePool (
1104 EfiBootServicesData
,
1105 sizeof (struct s_v2p
),
1109 if (Status
!= EFI_SUCCESS
) {
1113 Status
= mPciIoFncs
->Map (
1121 if (Status
!= EFI_SUCCESS
) {
1122 gBS
->FreePool (*v2p
);
1125 (*v2p
)->vaddr
= vaddr
;
1126 (*v2p
)->bsize
= bsize
;
1127 (*v2p
)->next
= _v2p
;
1140 Routine Description:
1141 This routine searches the linked list of mapped address nodes (for undi3.0
1142 interface) to find the node that corresponds to the given virtual address and
1143 returns a pointer to that node.
1146 v2p - pointer to return a map list node pointer.
1147 vaddr - virtual address (or CPU address) to be searched in the map list
1151 EFI_SUCEESS - if a match found!
1152 Other - match not found
1158 if (v2p
== NULL
|| vaddr
== NULL
) {
1159 return EFI_INVALID_PARAMETER
;
1162 for (v
= _v2p
; v
!= NULL
; v
= v
->next
) {
1163 if (v
->vaddr
== vaddr
) {
1169 return EFI_NOT_FOUND
;
1178 Routine Description:
1179 This routine unmaps the given virtual address and frees the memory allocated
1180 for the map list node corresponding to that address.
1183 vaddr - virtual address (or CPU address) to be unmapped
1186 EFI_SUCEESS - if successfully unmapped
1187 Other - as indicated by the error
1196 if (vaddr
== NULL
) {
1197 return EFI_INVALID_PARAMETER
;
1201 return EFI_NOT_FOUND
;
1204 // Is our node at the head of the list??
1206 if ((v
= _v2p
)->vaddr
== vaddr
) {
1209 Status
= mPciIoFncs
->Unmap (mPciIoFncs
, v
->unmap
);
1215 Print (L
"Unmap failed with status = %x\n", Status
);
1221 for (; v
->next
!= NULL
; v
= t
) {
1222 if ((t
= v
->next
)->vaddr
== vaddr
) {
1224 Status
= mPciIoFncs
->Unmap (mPciIoFncs
, t
->unmap
);
1228 Print (L
"Unmap failed with status = %x\n", Status
);
1235 return EFI_NOT_FOUND
;
1245 Routine Description:
1246 Wait for a key stroke, used for debugging purposes
1258 Aprint ("\nPress any key to continue\n");
1260 while (gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &key
) == EFI_NOT_READY
) {