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 (
44 DEBUG ((EFI_D_ERROR
, "\nissue_hwundi_command() - This should not be called!"));
47 return EFI_INVALID_PARAMETER
;
51 // %%TBD - For now, nothing is done.
53 return EFI_UNSUPPORTED
;
65 Compute 8-bit checksum of a buffer.
68 ptr - Pointer to buffer.
69 len - Length of buffer in bytes.
72 8-bit checksum of all bytes in buffer.
73 If ptr is NULL or len is zero, zero is returned.
83 if (ptr
== NULL
|| len
== 0) {
88 cksum
= (UINT8
) (cksum
+*bptr
++);
97 SimpleNetworkDriverSupported (
98 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
99 IN EFI_HANDLE Controller
,
100 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
105 Test to see if this driver supports Controller. Any Controller
106 that contains a Nii protocol can be supported.
109 This - Protocol instance pointer.
110 Controller - Handle of device to test.
111 RemainingDevicePath - Not used.
114 EFI_SUCCESS - This driver supports this device.
115 EFI_ALREADY_STARTED - This driver is already running on this device.
116 other - This driver does not support this device.
121 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL
*NiiProtocol
;
126 Status
= gBS
->OpenProtocol (
128 &gEfiDevicePathProtocolGuid
,
130 This
->DriverBindingHandle
,
132 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
134 if (EFI_ERROR (Status
)) {
138 Status
= gBS
->OpenProtocol (
140 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
141 (VOID
**) &NiiProtocol
,
142 This
->DriverBindingHandle
,
144 EFI_OPEN_PROTOCOL_BY_DRIVER
146 if (Status
== EFI_ALREADY_STARTED
)
148 DEBUG ((EFI_D_INFO
, "Support(): Already Started. on handle %x\n", Controller
));
149 return EFI_ALREADY_STARTED
;
152 if (!EFI_ERROR (Status
))
154 DEBUG ((EFI_D_INFO
, "Support(): UNDI3.1 found on handle %x\n", Controller
));
158 // try the older 3.0 driver
160 Status
= gBS
->OpenProtocol (
162 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
163 (VOID
**) &NiiProtocol
,
164 This
->DriverBindingHandle
,
166 EFI_OPEN_PROTOCOL_BY_DRIVER
168 if (EFI_ERROR (Status
)) {
172 DEBUG ((EFI_D_INFO
, "Support(): UNDI3.0 found on handle %x\n", Controller
));
175 // check the version, we don't want to connect to the undi16
177 if (NiiProtocol
->Type
!= EfiNetworkInterfaceUndi
) {
178 Status
= EFI_UNSUPPORTED
;
182 // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.
184 if (NiiProtocol
->ID
& 0x0F) {
185 DEBUG ((EFI_D_NET
, "\n!PXE structure is not paragraph aligned.\n"));
186 Status
= EFI_UNSUPPORTED
;
190 pxe
= (PXE_UNDI
*) (UINTN
) (NiiProtocol
->ID
);
193 // Verify !PXE revisions.
195 if (pxe
->hw
.Signature
!= PXE_ROMID_SIGNATURE
) {
196 DEBUG ((EFI_D_NET
, "\n!PXE signature is not valid.\n"));
197 Status
= EFI_UNSUPPORTED
;
201 if (pxe
->hw
.Rev
< PXE_ROMID_REV
) {
202 DEBUG ((EFI_D_NET
, "\n!PXE.Rev is not supported.\n"));
203 Status
= EFI_UNSUPPORTED
;
207 if (pxe
->hw
.MajorVer
< PXE_ROMID_MAJORVER
) {
209 DEBUG ((EFI_D_NET
, "\n!PXE.MajorVer is not supported.\n"));
210 Status
= EFI_UNSUPPORTED
;
213 } else if (pxe
->hw
.MajorVer
== PXE_ROMID_MAJORVER
&& pxe
->hw
.MinorVer
< PXE_ROMID_MINORVER
) {
214 DEBUG ((EFI_D_NET
, "\n!PXE.MinorVer is not supported."));
215 Status
= EFI_UNSUPPORTED
;
219 // Do S/W UNDI specific checks.
221 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_HW_UNDI
) == 0) {
222 if (pxe
->sw
.EntryPoint
< pxe
->sw
.Len
) {
223 DEBUG ((EFI_D_NET
, "\n!PXE S/W entry point is not valid."));
224 Status
= EFI_UNSUPPORTED
;
228 if (pxe
->sw
.BusCnt
== 0) {
229 DEBUG ((EFI_D_NET
, "\n!PXE.BusCnt is zero."));
230 Status
= EFI_UNSUPPORTED
;
235 Status
= EFI_SUCCESS
;
236 DEBUG ((EFI_D_INFO
, "Support(): supported on %x\n", Controller
));
242 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
243 This
->DriverBindingHandle
,
250 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
251 This
->DriverBindingHandle
,
262 SimpleNetworkDriverStart (
263 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
264 IN EFI_HANDLE Controller
,
265 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
270 called for any handle that we said "supported" in the above call!
273 This - Protocol instance pointer.
274 Controller - Handle of device to start
275 RemainingDevicePath - Not used.
278 EFI_SUCCESS - This driver supports this device.
279 other - This driver failed to start this device.
283 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL
*Nii
;
284 EFI_DEVICE_PATH_PROTOCOL
*NiiDevicePath
;
290 EFI_PHYSICAL_ADDRESS paddr
;
294 PXE_PCI_CONFIG_INFO ConfigInfo
;
295 PCI_TYPE00
*ConfigHeader
;
298 PXE_STATFLAGS InitStatFlags
;
300 DEBUG ((EFI_D_NET
, "\nSnpNotifyNetworkInterfaceIdentifier() "));
302 Status
= gBS
->OpenProtocol (
304 &gEfiDevicePathProtocolGuid
,
305 (VOID
**) &NiiDevicePath
,
306 This
->DriverBindingHandle
,
308 EFI_OPEN_PROTOCOL_BY_DRIVER
311 if (EFI_ERROR (Status
)) {
315 Status
= gBS
->LocateDevicePath (
316 &gEfiPciIoProtocolGuid
,
321 if (EFI_ERROR (Status
)) {
325 Status
= gBS
->OpenProtocol (
327 &gEfiPciIoProtocolGuid
,
328 (VOID
**) &mPciIoFncs
,
329 This
->DriverBindingHandle
,
331 EFI_OPEN_PROTOCOL_GET_PROTOCOL
333 if (EFI_ERROR (Status
)) {
337 // Get the NII interface. look for 3.1 undi first, if it is not there
338 // then look for 3.0, validate the interface.
340 Status
= gBS
->OpenProtocol (
342 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
344 This
->DriverBindingHandle
,
346 EFI_OPEN_PROTOCOL_BY_DRIVER
348 if (Status
== EFI_ALREADY_STARTED
) {
351 &gEfiDevicePathProtocolGuid
,
352 This
->DriverBindingHandle
,
358 if (!EFI_ERROR (Status
)) {
360 // probably not a 3.1 UNDI
363 DEBUG ((EFI_D_INFO
, "Start(): UNDI3.1 found\n"));
367 Status
= gBS
->OpenProtocol (
369 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
371 This
->DriverBindingHandle
,
373 EFI_OPEN_PROTOCOL_BY_DRIVER
375 if (EFI_ERROR (Status
)) {
378 &gEfiDevicePathProtocolGuid
,
379 This
->DriverBindingHandle
,
386 DEBUG ((EFI_D_INFO
, "Start(): UNDI3.0 found\n"));
389 pxe
= (PXE_UNDI
*) (UINTN
) (Nii
->ID
);
391 if (calc_8bit_cksum (pxe
, pxe
->hw
.Len
) != 0) {
392 DEBUG ((EFI_D_NET
, "\n!PXE checksum is not correct.\n"));
396 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
) != 0) {
398 // We can get any packets.
400 } else if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
) != 0) {
402 // We need to be able to get broadcast packets for DHCP.
403 // If we do not have promiscuous support, we must at least have
404 // broadcast support or we cannot do DHCP!
407 DEBUG ((EFI_D_NET
, "\nUNDI does not have promiscuous or broadcast support."));
411 // OK, we like this UNDI, and we know snp is not already there on this handle
412 // Allocate and initialize a new simple network protocol structure.
414 Status
= mPciIoFncs
->AllocateBuffer (
418 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
423 if (Status
!= EFI_SUCCESS
) {
424 DEBUG ((EFI_D_NET
, "\nCould not allocate SNP_DRIVER structure.\n"));
428 snp
= (SNP_DRIVER
*) (UINTN
) addr
;
431 Size
= SNP_MEM_PAGES (sizeof (SNP_DRIVER
));
433 Status
= mPciIoFncs
->Map (
435 EfiPciIoOperationBusMasterCommonBuffer
,
444 DEBUG ((EFI_D_NET
, "\nSNP_DRIVER @ %Xh, sizeof(SNP_DRIVER) == %d", addr
, sizeof (SNP_DRIVER
)));
445 snp
= (SNP_DRIVER
*) (UINTN
) paddr
;
446 snp
->SnpDriverUnmap
= addrUnmap
;
449 ZeroMem (snp
, sizeof (SNP_DRIVER
));
451 snp
->IoFncs
= mPciIoFncs
;
452 snp
->IsOldUndi
= (BOOLEAN
) (!UndiNew
);
454 snp
->Signature
= SNP_DRIVER_SIGNATURE
;
456 EfiInitializeLock (&snp
->lock
, EFI_TPL_NOTIFY
);
458 snp
->snp
.Revision
= EFI_SIMPLE_NETWORK_PROTOCOL_REVISION
;
459 snp
->snp
.Start
= snp_undi32_start
;
460 snp
->snp
.Stop
= snp_undi32_stop
;
461 snp
->snp
.Initialize
= snp_undi32_initialize
;
462 snp
->snp
.Reset
= snp_undi32_reset
;
463 snp
->snp
.Shutdown
= snp_undi32_shutdown
;
464 snp
->snp
.ReceiveFilters
= snp_undi32_receive_filters
;
465 snp
->snp
.StationAddress
= snp_undi32_station_address
;
466 snp
->snp
.Statistics
= snp_undi32_statistics
;
467 snp
->snp
.MCastIpToMac
= snp_undi32_mcast_ip_to_mac
;
468 snp
->snp
.NvData
= snp_undi32_nvdata
;
469 snp
->snp
.GetStatus
= snp_undi32_get_status
;
470 snp
->snp
.Transmit
= snp_undi32_transmit
;
471 snp
->snp
.Receive
= snp_undi32_receive
;
472 snp
->snp
.WaitForPacket
= NULL
;
474 snp
->snp
.Mode
= &snp
->mode
;
476 snp
->tx_rx_bufsize
= 0;
477 snp
->tx_rx_buffer
= NULL
;
479 snp
->if_num
= Nii
->IfNum
;
481 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_HW_UNDI
) != 0) {
482 snp
->is_swundi
= FALSE
;
483 snp
->issue_undi32_command
= &issue_hwundi_command
;
485 snp
->is_swundi
= TRUE
;
487 if ((pxe
->sw
.Implementation
& PXE_ROMID_IMP_SW_VIRT_ADDR
) != 0) {
488 snp
->issue_undi32_command
= (issue_undi32_command
) (UINTN
) pxe
->sw
.EntryPoint
;
490 snp
->issue_undi32_command
= (issue_undi32_command
) (UINTN
) ((UINT8
) (UINTN
) pxe
+ pxe
->sw
.EntryPoint
);
494 // Allocate a global CPB and DB buffer for this UNDI interface.
495 // we do this because:
497 // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be
498 // within 2GB limit, create them here and map them so that when undi calls
499 // v2p callback to check if the physical address is < 2gb, we will pass.
501 // -This is not a requirement for 3.1 or later UNDIs but the code looks
502 // simpler if we use the same cpb, db variables for both old and new undi
503 // interfaces from all the SNP interface calls (we don't map the buffers
504 // for the newer undi interfaces though)
506 // -it is OK to allocate one global set of CPB, DB pair for each UNDI
507 // interface as EFI does not multi-task and so SNP will not be re-entered!
509 Status
= mPciIoFncs
->AllocateBuffer (
513 SNP_MEM_PAGES (4096),
518 if (Status
!= EFI_SUCCESS
) {
519 DEBUG ((EFI_D_NET
, "\nCould not allocate CPB and DB structures.\n"));
520 goto Error_DeleteSNP
;
523 if (snp
->IsOldUndi
) {
524 Size
= SNP_MEM_PAGES (4096);
526 Status
= mPciIoFncs
->Map (
528 EfiPciIoOperationBusMasterCommonBuffer
,
537 snp
->cpb
= (VOID
*) (UINTN
) paddr
;
538 snp
->db
= (VOID
*) ((UINTN
) paddr
+ 2048);
540 snp
->cpb
= (VOID
*) (UINTN
) addr
;
541 snp
->db
= (VOID
*) ((UINTN
) addr
+ 2048);
544 // pxe_start call is going to give the callback functions to UNDI, these callback
545 // functions use the BarIndex values from the snp structure, so these must be initialized
546 // with default values before doing a pxe_start. The correct values can be obtained after
547 // getting the config information from UNDI
549 snp
->MemoryBarIndex
= 0;
553 // we need the undi init information many times in this snp code, just get it
554 // once here and store it in the snp driver structure. to get Init Info
555 // from UNDI we have to start undi first.
557 Status
= pxe_start (snp
);
559 if (Status
!= EFI_SUCCESS
) {
560 goto Error_DeleteCPBDB
;
563 snp
->cdb
.OpCode
= PXE_OPCODE_GET_INIT_INFO
;
564 snp
->cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
566 snp
->cdb
.CPBsize
= PXE_CPBSIZE_NOT_USED
;
567 snp
->cdb
.CPBaddr
= PXE_DBADDR_NOT_USED
;
569 snp
->cdb
.DBsize
= sizeof snp
->init_info
;
570 snp
->cdb
.DBaddr
= (UINT64
) (UINTN
) &snp
->init_info
;
572 snp
->cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
573 snp
->cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
575 snp
->cdb
.IFnum
= snp
->if_num
;
576 snp
->cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
578 DEBUG ((EFI_D_NET
, "\nsnp->undi.get_init_info() "));
580 (*snp
->issue_undi32_command
) ((UINT64
) (UINTN
) &snp
->cdb
);
583 // Save the INIT Stat Code...
585 InitStatFlags
= snp
->cdb
.StatFlags
;
587 if (snp
->cdb
.StatCode
!= PXE_STATCODE_SUCCESS
) {
588 DEBUG ((EFI_D_NET
, "\nsnp->undi.init_info() %xh:%xh\n", snp
->cdb
.StatFlags
, snp
->cdb
.StatCode
));
590 goto Error_DeleteCPBDB
;
593 snp
->cdb
.OpCode
= PXE_OPCODE_GET_CONFIG_INFO
;
594 snp
->cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
596 snp
->cdb
.CPBsize
= PXE_CPBSIZE_NOT_USED
;
597 snp
->cdb
.CPBaddr
= PXE_DBADDR_NOT_USED
;
599 snp
->cdb
.DBsize
= sizeof ConfigInfo
;
600 snp
->cdb
.DBaddr
= (UINT64
) (UINTN
) &ConfigInfo
;
602 snp
->cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
603 snp
->cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
605 snp
->cdb
.IFnum
= snp
->if_num
;
606 snp
->cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
608 DEBUG ((EFI_D_NET
, "\nsnp->undi.get_config_info() "));
610 (*snp
->issue_undi32_command
) ((UINT64
) (UINTN
) &snp
->cdb
);
612 if (snp
->cdb
.StatCode
!= PXE_STATCODE_SUCCESS
) {
613 DEBUG ((EFI_D_NET
, "\nsnp->undi.config_info() %xh:%xh\n", snp
->cdb
.StatFlags
, snp
->cdb
.StatCode
));
615 goto Error_DeleteCPBDB
;
618 // Find the correct BAR to do IO.
621 // Enumerate through the PCI BARs for the device to determine which one is
622 // the IO BAR. Save the index of the BAR into the adapter info structure.
623 // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped
625 ConfigHeader
= (PCI_TYPE00
*) &ConfigInfo
.Config
.Byte
[0];
626 TempBar
= (UINT32
*) &ConfigHeader
->Device
.Bar
[0];
627 for (BarIndex
= 0; BarIndex
<= 5; BarIndex
++) {
628 if ((*TempBar
& PCI_BAR_MEM_MASK
) == PCI_BAR_MEM_64BIT
) {
630 // This is a 64-bit memory bar, skip this and the
636 if ((*TempBar
& PCI_BAR_IO_MASK
) == PCI_BAR_IO_MODE
) {
637 snp
->IoBarIndex
= BarIndex
;
645 // We allocate 2 more global buffers for undi 3.0 interface. We use these
646 // buffers to pass to undi when the user buffers are beyond 4GB.
647 // UNDI 3.0 wants all the addresses passed to it to be
648 // within 2GB limit, create them here and map them so that when undi calls
649 // v2p callback to check if the physical address is < 2gb, we will pass.
651 // For 3.1 and later UNDIs, we do not do this because undi is
652 // going to call the map() callback if and only if it wants to use the
653 // device address for any address it receives.
655 if (snp
->IsOldUndi
) {
657 // buffer for receive
659 Size
= SNP_MEM_PAGES (snp
->init_info
.MediaHeaderLen
+ snp
->init_info
.FrameDataLen
);
660 Status
= mPciIoFncs
->AllocateBuffer (
669 if (Status
!= EFI_SUCCESS
) {
670 DEBUG ((EFI_D_ERROR
, "\nCould not allocate receive buffer.\n"));
671 goto Error_DeleteCPBDB
;
674 Status
= mPciIoFncs
->Map (
676 EfiPciIoOperationBusMasterCommonBuffer
,
680 &snp
->ReceiveBufUnmap
685 snp
->receive_buf
= (UINT8
*) (UINTN
) paddr
;
688 // buffer for fill_header
690 Size
= SNP_MEM_PAGES (snp
->init_info
.MediaHeaderLen
);
691 Status
= mPciIoFncs
->AllocateBuffer (
700 if (Status
!= EFI_SUCCESS
) {
701 DEBUG ((EFI_D_ERROR
, "\nCould not allocate fill_header buffer.\n"));
702 goto Error_DeleteRCVBuf
;
705 Status
= mPciIoFncs
->Map (
707 EfiPciIoOperationBusMasterCommonBuffer
,
711 &snp
->FillHdrBufUnmap
715 snp
->fill_hdr_buf
= (UINT8
*) (UINTN
) paddr
;
718 // Initialize simple network protocol mode structure
720 snp
->mode
.State
= EfiSimpleNetworkStopped
;
721 snp
->mode
.HwAddressSize
= snp
->init_info
.HWaddrLen
;
722 snp
->mode
.MediaHeaderSize
= snp
->init_info
.MediaHeaderLen
;
723 snp
->mode
.MaxPacketSize
= snp
->init_info
.FrameDataLen
;
724 snp
->mode
.NvRamAccessSize
= snp
->init_info
.NvWidth
;
725 snp
->mode
.NvRamSize
= snp
->init_info
.NvCount
* snp
->mode
.NvRamAccessSize
;
726 snp
->mode
.IfType
= snp
->init_info
.IFtype
;
727 snp
->mode
.MaxMCastFilterCount
= snp
->init_info
.MCastFilterCnt
;
728 snp
->mode
.MCastFilterCount
= 0;
730 switch (InitStatFlags
& PXE_STATFLAGS_CABLE_DETECT_MASK
) {
731 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED
:
732 snp
->mode
.MediaPresentSupported
= TRUE
;
735 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED
:
737 snp
->mode
.MediaPresentSupported
= FALSE
;
740 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_STATION_ADDR_SETTABLE
) != 0) {
741 snp
->mode
.MacAddressChangeable
= TRUE
;
743 snp
->mode
.MacAddressChangeable
= FALSE
;
746 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED
) != 0) {
747 snp
->mode
.MultipleTxSupported
= TRUE
;
749 snp
->mode
.MultipleTxSupported
= FALSE
;
752 snp
->mode
.ReceiveFilterMask
= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
754 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
) != 0) {
755 snp
->mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
759 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
) != 0) {
760 snp
->mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
764 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
) != 0) {
765 snp
->mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
769 if ((pxe
->hw
.Implementation
& PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED
) != 0) {
770 snp
->mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
774 if (pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
) {
775 snp
->mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
779 snp
->mode
.ReceiveFilterSetting
= 0;
782 // need to get the station address to save in the mode structure. we need to
783 // initialize the UNDI first for this.
785 snp
->tx_rx_bufsize
= snp
->init_info
.MemoryRequired
;
786 Status
= pxe_init (snp
, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE
);
790 goto Error_DeleteHdrBuf
;
793 Status
= pxe_get_stn_addr (snp
);
795 if (Status
!= EFI_SUCCESS
) {
796 DEBUG ((EFI_D_ERROR
, "\nsnp->undi.get_station_addr() failed.\n"));
799 goto Error_DeleteHdrBuf
;
802 snp
->mode
.MediaPresent
= FALSE
;
805 // We should not leave UNDI started and initialized here. this DriverStart()
806 // routine must only find and attach the SNP interface to UNDI layer that it
807 // finds on the given handle!
808 // The UNDI layer will be started when upper layers call snp->start.
809 // How ever, this DriverStart() must fill up the snp mode structure which
810 // contains the MAC address of the NIC. For this reason we started and
811 // initialized UNDI here, now we are done, do a shutdown and stop of the
818 // add SNP to the undi handle
820 Status
= gBS
->InstallProtocolInterface (
822 &gEfiSimpleNetworkProtocolGuid
,
823 EFI_NATIVE_INTERFACE
,
827 if (!EFI_ERROR (Status
)) {
832 if (snp
->IsOldUndi
) {
833 Status
= mPciIoFncs
->Unmap (
837 Size
= SNP_MEM_PAGES (snp
->init_info
.MediaHeaderLen
);
838 mPciIoFncs
->FreeBuffer (
846 if (snp
->IsOldUndi
) {
847 Status
= mPciIoFncs
->Unmap (
851 Size
= SNP_MEM_PAGES (snp
->init_info
.MediaHeaderLen
+ snp
->init_info
.FrameDataLen
);
852 mPciIoFncs
->FreeBuffer (
861 if (snp
->IsOldUndi
) {
862 Status
= mPciIoFncs
->Unmap (
868 Status
= mPciIoFncs
->FreeBuffer (
870 SNP_MEM_PAGES (4096),
875 if (snp
->IsOldUndi
) {
876 Status
= mPciIoFncs
->Unmap (
882 mPciIoFncs
->FreeBuffer (
884 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
891 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
892 This
->DriverBindingHandle
,
898 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
899 This
->DriverBindingHandle
,
906 &gEfiDevicePathProtocolGuid
,
907 This
->DriverBindingHandle
,
917 SimpleNetworkDriverStop (
918 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
919 IN EFI_HANDLE Controller
,
920 IN UINTN NumberOfChildren
,
921 IN EFI_HANDLE
*ChildHandleBuffer
934 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpProtocol
;
938 // Get our context back.
940 Status
= gBS
->OpenProtocol (
942 &gEfiSimpleNetworkProtocolGuid
,
943 (VOID
**) &SnpProtocol
,
944 This
->DriverBindingHandle
,
946 EFI_OPEN_PROTOCOL_GET_PROTOCOL
949 if (EFI_ERROR (Status
)) {
950 return EFI_UNSUPPORTED
;
953 Snp
= EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol
);
955 Status
= gBS
->UninstallProtocolInterface (
957 &gEfiSimpleNetworkProtocolGuid
,
961 if (EFI_ERROR (Status
)) {
965 if (!Snp
->IsOldUndi
) {
966 Status
= gBS
->CloseProtocol (
968 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
969 This
->DriverBindingHandle
,
973 Status
= gBS
->CloseProtocol (
975 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
976 This
->DriverBindingHandle
,
981 Status
= gBS
->CloseProtocol (
983 &gEfiDevicePathProtocolGuid
,
984 This
->DriverBindingHandle
,
991 if (Snp
->IsOldUndi
) {
992 Status
= mPciIoFncs
->Unmap (
997 mPciIoFncs
->FreeBuffer (
999 SNP_MEM_PAGES (Snp
->init_info
.MediaHeaderLen
),
1002 Status
= mPciIoFncs
->Unmap (
1004 Snp
->ReceiveBufUnmap
1007 mPciIoFncs
->FreeBuffer (
1009 SNP_MEM_PAGES (Snp
->init_info
.MediaHeaderLen
+ Snp
->init_info
.FrameDataLen
),
1013 Status
= mPciIoFncs
->Unmap (
1017 Status
= mPciIoFncs
->Unmap (
1023 mPciIoFncs
->FreeBuffer (
1025 SNP_MEM_PAGES (4096),
1029 mPciIoFncs
->FreeBuffer (
1031 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
1039 // Simple Network Protocol Driver Global Variables
1041 EFI_DRIVER_BINDING_PROTOCOL mSimpleNetworkDriverBinding
= {
1042 SimpleNetworkDriverSupported
,
1043 SimpleNetworkDriverStart
,
1044 SimpleNetworkDriverStop
,
1052 IN OUT
struct s_v2p
**v2p
,
1053 EFI_PCI_IO_PROTOCOL_OPERATION type
,
1059 Routine Description:
1060 This routine maps the given CPU address to a Device address. It creates a
1061 an entry in the map list with the virtual and physical addresses and the
1065 v2p - pointer to return a map list node pointer.
1066 type - the direction in which the data flows from the given virtual address
1067 device->cpu or cpu->device or both ways.
1068 vaddr - virtual address (or CPU address) to be mapped
1069 bsize - size of the buffer to be mapped.
1073 EFI_SUCEESS - routine has completed the mapping
1074 other - error as indicated.
1080 if ((v2p
== NULL
) || (vaddr
== NULL
) || (bsize
== 0)) {
1081 return EFI_INVALID_PARAMETER
;
1084 Status
= gBS
->AllocatePool (
1085 EfiBootServicesData
,
1086 sizeof (struct s_v2p
),
1090 if (Status
!= EFI_SUCCESS
) {
1094 Status
= mPciIoFncs
->Map (
1102 if (Status
!= EFI_SUCCESS
) {
1103 gBS
->FreePool (*v2p
);
1106 (*v2p
)->vaddr
= vaddr
;
1107 (*v2p
)->bsize
= bsize
;
1108 (*v2p
)->next
= _v2p
;
1121 Routine Description:
1122 This routine searches the linked list of mapped address nodes (for undi3.0
1123 interface) to find the node that corresponds to the given virtual address and
1124 returns a pointer to that node.
1127 v2p - pointer to return a map list node pointer.
1128 vaddr - virtual address (or CPU address) to be searched in the map list
1132 EFI_SUCEESS - if a match found!
1133 Other - match not found
1139 if (v2p
== NULL
|| vaddr
== NULL
) {
1140 return EFI_INVALID_PARAMETER
;
1143 for (v
= _v2p
; v
!= NULL
; v
= v
->next
) {
1144 if (v
->vaddr
== vaddr
) {
1150 return EFI_NOT_FOUND
;
1159 Routine Description:
1160 This routine unmaps the given virtual address and frees the memory allocated
1161 for the map list node corresponding to that address.
1164 vaddr - virtual address (or CPU address) to be unmapped
1167 EFI_SUCEESS - if successfully unmapped
1168 Other - as indicated by the error
1177 if (vaddr
== NULL
) {
1178 return EFI_INVALID_PARAMETER
;
1182 return EFI_NOT_FOUND
;
1185 // Is our node at the head of the list??
1187 if ((v
= _v2p
)->vaddr
== vaddr
) {
1190 Status
= mPciIoFncs
->Unmap (mPciIoFncs
, v
->unmap
);
1195 DEBUG ((EFI_D_ERROR
, "Unmap failed with status = %x\n", Status
));
1200 for (; v
->next
!= NULL
; v
= t
) {
1201 if ((t
= v
->next
)->vaddr
== vaddr
) {
1203 Status
= mPciIoFncs
->Unmap (mPciIoFncs
, t
->unmap
);
1207 DEBUG ((EFI_D_ERROR
, "Unmap failed with status = %x\n", Status
));
1213 return EFI_NOT_FOUND
;