2 Copyright (c) 2004 - 2005, Intel Corporation
\r
3 All rights reserved. This program and the accompanying materials
\r
4 are licensed and made available under the terms and conditions of the BSD License
\r
5 which accompanies this distribution. The full text of the license may be found at
\r
6 http://opensource.org/licenses/bsd-license.php
\r
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
\r
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
\r
45 InitializeSnpNiiDriver (
\r
46 IN EFI_HANDLE image_handle,
\r
47 IN EFI_SYSTEM_TABLE *system_table
\r
52 SimpleNetworkDriverSupported (
\r
53 IN EFI_DRIVER_BINDING_PROTOCOL *This,
\r
54 IN EFI_HANDLE Controller,
\r
55 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
\r
60 SimpleNetworkDriverStart (
\r
61 IN EFI_DRIVER_BINDING_PROTOCOL *This,
\r
62 IN EFI_HANDLE Controller,
\r
63 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
\r
68 SimpleNetworkDriverStop (
\r
69 IN EFI_DRIVER_BINDING_PROTOCOL *This,
\r
70 IN EFI_HANDLE Controller,
\r
71 IN UINTN NumberOfChildren,
\r
72 IN EFI_HANDLE *ChildHandleBuffer
\r
76 // Simple Network Protocol Driver Global Variables
\r
78 EFI_DRIVER_BINDING_PROTOCOL mSimpleNetworkDriverBinding = {
\r
79 SimpleNetworkDriverSupported,
\r
80 SimpleNetworkDriverStart,
\r
81 SimpleNetworkDriverStop,
\r
88 // Module global variables needed to support undi 3.0 interface
\r
90 EFI_PCI_IO_PROTOCOL *mPciIoFncs;
\r
91 struct s_v2p *_v2p = NULL; // undi3.0 map_list head
\r
92 // End Global variables
\r
96 This routine maps the given CPU address to a Device address. It creates a
\r
97 an entry in the map list with the virtual and physical addresses and the
\r
100 @param v2p pointer to return a map list node pointer.
\r
101 @param type the direction in which the data flows from the given
\r
102 virtual address device->cpu or cpu->device or both
\r
104 @param vaddr virtual address (or CPU address) to be mapped
\r
105 @param bsize size of the buffer to be mapped.
\r
107 @retval EFI_SUCEESS routine has completed the mapping
\r
108 @retval other error as indicated.
\r
113 IN OUT struct s_v2p **v2p,
\r
114 EFI_PCI_IO_PROTOCOL_OPERATION type,
\r
121 if ((v2p == NULL) || (vaddr == NULL) || (bsize == 0)) {
\r
122 return EFI_INVALID_PARAMETER;
\r
125 *v2p = AllocatePool (sizeof (struct s_v2p));
\r
126 if (*v2p != NULL) {
\r
127 return EFI_OUT_OF_RESOURCES;
\r
130 Status = mPciIoFncs->Map (
\r
138 if (Status != EFI_SUCCESS) {
\r
142 (*v2p)->vaddr = vaddr;
\r
143 (*v2p)->bsize = bsize;
\r
144 (*v2p)->next = _v2p;
\r
147 return EFI_SUCCESS;
\r
152 This routine searches the linked list of mapped address nodes (for undi3.0
\r
153 interface) to find the node that corresponds to the given virtual address and
\r
154 returns a pointer to that node.
\r
156 @param v2p pointer to return a map list node pointer.
\r
157 @param vaddr virtual address (or CPU address) to be searched in
\r
160 @retval EFI_SUCEESS if a match found!
\r
161 @retval Other match not found
\r
166 struct s_v2p **v2p,
\r
172 if (v2p == NULL || vaddr == NULL) {
\r
173 return EFI_INVALID_PARAMETER;
\r
176 for (v = _v2p; v != NULL; v = v->next) {
\r
177 if (v->vaddr == vaddr) {
\r
179 return EFI_SUCCESS;
\r
183 return EFI_NOT_FOUND;
\r
188 This routine unmaps the given virtual address and frees the memory allocated
\r
189 for the map list node corresponding to that address.
\r
191 @param vaddr virtual address (or CPU address) to be unmapped
\r
193 @retval EFI_SUCEESS if successfully unmapped
\r
194 @retval Other as indicated by the error
\r
206 if (vaddr == NULL) {
\r
207 return EFI_INVALID_PARAMETER;
\r
210 if (_v2p == NULL) {
\r
211 return EFI_NOT_FOUND;
\r
214 // Is our node at the head of the list??
\r
216 if ((v = _v2p)->vaddr == vaddr) {
\r
219 Status = mPciIoFncs->Unmap (mPciIoFncs, v->unmap);
\r
224 DEBUG ((EFI_D_ERROR, "Unmap failed with status = %x\n", Status));
\r
229 for (; v->next != NULL; v = t) {
\r
230 if ((t = v->next)->vaddr == vaddr) {
\r
232 Status = mPciIoFncs->Unmap (mPciIoFncs, t->unmap);
\r
236 DEBUG ((EFI_D_ERROR, "Unmap failed with status = %x\n", Status));
\r
242 return EFI_NOT_FOUND;
\r
247 issue_hwundi_command (
\r
252 Routine Description:
\r
260 DEBUG ((EFI_D_ERROR, "\nissue_hwundi_command() - This should not be called!"));
\r
263 return EFI_INVALID_PARAMETER;
\r
267 // %%TBD - For now, nothing is done.
\r
269 return EFI_UNSUPPORTED;
\r
274 Compute 8-bit checksum of a buffer.
\r
276 @param ptr Pointer to buffer.
\r
277 @param len Length of buffer in bytes.
\r
279 @return 8-bit checksum of all bytes in buffer.
\r
280 @return If ptr is NULL or len is zero, zero is returned.
\r
296 if (ptr == NULL || len == 0) {
\r
301 cksum = (UINT8) (cksum +*bptr++);
\r
309 Test to see if this driver supports Controller. Any Controller
\r
310 that contains a Nii protocol can be supported.
\r
312 @param This Protocol instance pointer.
\r
313 @param Controller Handle of device to test.
\r
314 @param RemainingDevicePath Not used.
\r
316 @retval EFI_SUCCESS This driver supports this device.
\r
317 @retval EFI_ALREADY_STARTED This driver is already running on this device.
\r
318 @retval other This driver does not support this device.
\r
323 SimpleNetworkDriverSupported (
\r
324 IN EFI_DRIVER_BINDING_PROTOCOL *This,
\r
325 IN EFI_HANDLE Controller,
\r
326 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
\r
330 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NiiProtocol;
\r
333 Status = gBS->OpenProtocol (
\r
335 &gEfiDevicePathProtocolGuid,
\r
337 This->DriverBindingHandle,
\r
339 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
\r
341 if (EFI_ERROR (Status)) {
\r
345 Status = gBS->OpenProtocol (
\r
347 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
\r
348 (VOID **) &NiiProtocol,
\r
349 This->DriverBindingHandle,
\r
351 EFI_OPEN_PROTOCOL_BY_DRIVER
\r
354 if (EFI_ERROR (Status)) {
\r
355 if (Status == EFI_ALREADY_STARTED) {
\r
356 DEBUG ((EFI_D_INFO, "Support(): Already Started. on handle %x\n", Controller));
\r
361 DEBUG ((EFI_D_INFO, "Support(): UNDI3.1 found on handle %x\n", Controller));
\r
364 // check the version, we don't want to connect to the undi16
\r
366 if (NiiProtocol->Type != EfiNetworkInterfaceUndi) {
\r
367 Status = EFI_UNSUPPORTED;
\r
371 // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.
\r
373 if (NiiProtocol->ID & 0x0F) {
\r
374 DEBUG ((EFI_D_NET, "\n!PXE structure is not paragraph aligned.\n"));
\r
375 Status = EFI_UNSUPPORTED;
\r
379 pxe = (PXE_UNDI *) (UINTN) (NiiProtocol->ID);
\r
382 // Verify !PXE revisions.
\r
384 if (pxe->hw.Signature != PXE_ROMID_SIGNATURE) {
\r
385 DEBUG ((EFI_D_NET, "\n!PXE signature is not valid.\n"));
\r
386 Status = EFI_UNSUPPORTED;
\r
390 if (pxe->hw.Rev < PXE_ROMID_REV) {
\r
391 DEBUG ((EFI_D_NET, "\n!PXE.Rev is not supported.\n"));
\r
392 Status = EFI_UNSUPPORTED;
\r
396 if (pxe->hw.MajorVer < PXE_ROMID_MAJORVER) {
\r
398 DEBUG ((EFI_D_NET, "\n!PXE.MajorVer is not supported.\n"));
\r
399 Status = EFI_UNSUPPORTED;
\r
402 } else if (pxe->hw.MajorVer == PXE_ROMID_MAJORVER && pxe->hw.MinorVer < PXE_ROMID_MINORVER) {
\r
403 DEBUG ((EFI_D_NET, "\n!PXE.MinorVer is not supported."));
\r
404 Status = EFI_UNSUPPORTED;
\r
408 // Do S/W UNDI specific checks.
\r
410 if ((pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) == 0) {
\r
411 if (pxe->sw.EntryPoint < pxe->sw.Len) {
\r
412 DEBUG ((EFI_D_NET, "\n!PXE S/W entry point is not valid."));
\r
413 Status = EFI_UNSUPPORTED;
\r
417 if (pxe->sw.BusCnt == 0) {
\r
418 DEBUG ((EFI_D_NET, "\n!PXE.BusCnt is zero."));
\r
419 Status = EFI_UNSUPPORTED;
\r
424 Status = EFI_SUCCESS;
\r
425 DEBUG ((EFI_D_INFO, "Support(): supported on %x\n", Controller));
\r
428 gBS->CloseProtocol (
\r
430 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
\r
431 This->DriverBindingHandle,
\r
440 called for any handle that we said "supported" in the above call!
\r
442 @param This Protocol instance pointer.
\r
443 @param Controller Handle of device to start
\r
444 @param RemainingDevicePath Not used.
\r
446 @retval EFI_SUCCESS This driver supports this device.
\r
447 @retval other This driver failed to start this device.
\r
452 SimpleNetworkDriverStart (
\r
453 IN EFI_DRIVER_BINDING_PROTOCOL *This,
\r
454 IN EFI_HANDLE Controller,
\r
455 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
\r
458 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii;
\r
459 EFI_DEVICE_PATH_PROTOCOL *NiiDevicePath;
\r
465 PXE_PCI_CONFIG_INFO ConfigInfo;
\r
466 PCI_TYPE00 *ConfigHeader;
\r
469 PXE_STATFLAGS InitStatFlags;
\r
471 DEBUG ((EFI_D_NET, "\nSnpNotifyNetworkInterfaceIdentifier() "));
\r
473 Status = gBS->OpenProtocol (
\r
475 &gEfiDevicePathProtocolGuid,
\r
476 (VOID **) &NiiDevicePath,
\r
477 This->DriverBindingHandle,
\r
479 EFI_OPEN_PROTOCOL_BY_DRIVER
\r
482 if (EFI_ERROR (Status)) {
\r
486 Status = gBS->LocateDevicePath (
\r
487 &gEfiPciIoProtocolGuid,
\r
492 if (EFI_ERROR (Status)) {
\r
496 Status = gBS->OpenProtocol (
\r
498 &gEfiPciIoProtocolGuid,
\r
499 (VOID **) &mPciIoFncs,
\r
500 This->DriverBindingHandle,
\r
502 EFI_OPEN_PROTOCOL_GET_PROTOCOL
\r
504 if (EFI_ERROR (Status)) {
\r
508 // Get the NII interface.
\r
510 Status = gBS->OpenProtocol (
\r
512 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
\r
514 This->DriverBindingHandle,
\r
516 EFI_OPEN_PROTOCOL_BY_DRIVER
\r
518 if (EFI_ERROR (Status)) {
\r
519 gBS->CloseProtocol (
\r
521 &gEfiDevicePathProtocolGuid,
\r
522 This->DriverBindingHandle,
\r
528 DEBUG ((EFI_D_INFO, "Start(): UNDI3.1 found\n"));
\r
530 pxe = (PXE_UNDI *) (UINTN) (Nii->ID);
\r
532 if (calc_8bit_cksum (pxe, pxe->hw.Len) != 0) {
\r
533 DEBUG ((EFI_D_NET, "\n!PXE checksum is not correct.\n"));
\r
537 if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {
\r
539 // We can get any packets.
\r
541 } else if ((pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {
\r
543 // We need to be able to get broadcast packets for DHCP.
\r
544 // If we do not have promiscuous support, we must at least have
\r
545 // broadcast support or we cannot do DHCP!
\r
548 DEBUG ((EFI_D_NET, "\nUNDI does not have promiscuous or broadcast support."));
\r
552 // OK, we like this UNDI, and we know snp is not already there on this handle
\r
553 // Allocate and initialize a new simple network protocol structure.
\r
555 Status = mPciIoFncs->AllocateBuffer (
\r
558 EfiBootServicesData,
\r
559 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),
\r
564 if (Status != EFI_SUCCESS) {
\r
565 DEBUG ((EFI_D_NET, "\nCould not allocate SNP_DRIVER structure.\n"));
\r
569 snp = (SNP_DRIVER *) (UINTN) addr;
\r
571 ZeroMem (snp, sizeof (SNP_DRIVER));
\r
573 snp->IoFncs = mPciIoFncs;
\r
574 snp->Signature = SNP_DRIVER_SIGNATURE;
\r
576 EfiInitializeLock (&snp->lock, TPL_NOTIFY);
\r
578 snp->snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
\r
579 snp->snp.Start = snp_undi32_start;
\r
580 snp->snp.Stop = snp_undi32_stop;
\r
581 snp->snp.Initialize = snp_undi32_initialize;
\r
582 snp->snp.Reset = snp_undi32_reset;
\r
583 snp->snp.Shutdown = snp_undi32_shutdown;
\r
584 snp->snp.ReceiveFilters = snp_undi32_receive_filters;
\r
585 snp->snp.StationAddress = snp_undi32_station_address;
\r
586 snp->snp.Statistics = snp_undi32_statistics;
\r
587 snp->snp.MCastIpToMac = snp_undi32_mcast_ip_to_mac;
\r
588 snp->snp.NvData = snp_undi32_nvdata;
\r
589 snp->snp.GetStatus = snp_undi32_get_status;
\r
590 snp->snp.Transmit = snp_undi32_transmit;
\r
591 snp->snp.Receive = snp_undi32_receive;
\r
592 snp->snp.WaitForPacket = NULL;
\r
594 snp->snp.Mode = &snp->mode;
\r
596 snp->tx_rx_bufsize = 0;
\r
597 snp->tx_rx_buffer = NULL;
\r
599 snp->if_num = Nii->IfNum;
\r
601 if ((pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) {
\r
602 snp->is_swundi = FALSE;
\r
603 snp->issue_undi32_command = &issue_hwundi_command;
\r
605 snp->is_swundi = TRUE;
\r
607 if ((pxe->sw.Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR) != 0) {
\r
608 snp->issue_undi32_command = (issue_undi32_command) (UINTN) pxe->sw.EntryPoint;
\r
610 snp->issue_undi32_command = (issue_undi32_command) (UINTN) ((UINT8) (UINTN) pxe + pxe->sw.EntryPoint);
\r
614 // Allocate a global CPB and DB buffer for this UNDI interface.
\r
615 // we do this because:
\r
617 // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be
\r
618 // within 2GB limit, create them here and map them so that when undi calls
\r
619 // v2p callback to check if the physical address is < 2gb, we will pass.
\r
621 // -This is not a requirement for 3.1 or later UNDIs but the code looks
\r
622 // simpler if we use the same cpb, db variables for both old and new undi
\r
623 // interfaces from all the SNP interface calls (we don't map the buffers
\r
624 // for the newer undi interfaces though)
\r
626 // -it is OK to allocate one global set of CPB, DB pair for each UNDI
\r
627 // interface as EFI does not multi-task and so SNP will not be re-entered!
\r
629 Status = mPciIoFncs->AllocateBuffer (
\r
632 EfiBootServicesData,
\r
633 SNP_MEM_PAGES (4096),
\r
638 if (Status != EFI_SUCCESS) {
\r
639 DEBUG ((EFI_D_NET, "\nCould not allocate CPB and DB structures.\n"));
\r
640 goto Error_DeleteSNP;
\r
643 snp->cpb = (VOID *) (UINTN) addr;
\r
644 snp->db = (VOID *) ((UINTN) addr + 2048);
\r
647 // pxe_start call is going to give the callback functions to UNDI, these callback
\r
648 // functions use the BarIndex values from the snp structure, so these must be initialized
\r
649 // with default values before doing a pxe_start. The correct values can be obtained after
\r
650 // getting the config information from UNDI
\r
652 snp->MemoryBarIndex = 0;
\r
653 snp->IoBarIndex = 1;
\r
656 // we need the undi init information many times in this snp code, just get it
\r
657 // once here and store it in the snp driver structure. to get Init Info
\r
658 // from UNDI we have to start undi first.
\r
660 Status = pxe_start (snp);
\r
662 if (Status != EFI_SUCCESS) {
\r
663 goto Error_DeleteSNP;
\r
666 snp->cdb.OpCode = PXE_OPCODE_GET_INIT_INFO;
\r
667 snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
\r
669 snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
\r
670 snp->cdb.CPBaddr = PXE_DBADDR_NOT_USED;
\r
672 snp->cdb.DBsize = sizeof snp->init_info;
\r
673 snp->cdb.DBaddr = (UINT64)(UINTN) &snp->init_info;
\r
675 snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
\r
676 snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
\r
678 snp->cdb.IFnum = snp->if_num;
\r
679 snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
\r
681 DEBUG ((EFI_D_NET, "\nsnp->undi.get_init_info() "));
\r
683 (*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
\r
686 // Save the INIT Stat Code...
\r
688 InitStatFlags = snp->cdb.StatFlags;
\r
690 if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
\r
691 DEBUG ((EFI_D_NET, "\nsnp->undi.init_info() %xh:%xh\n", snp->cdb.StatFlags, snp->cdb.StatCode));
\r
693 goto Error_DeleteSNP;
\r
696 snp->cdb.OpCode = PXE_OPCODE_GET_CONFIG_INFO;
\r
697 snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
\r
699 snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
\r
700 snp->cdb.CPBaddr = PXE_DBADDR_NOT_USED;
\r
702 snp->cdb.DBsize = sizeof ConfigInfo;
\r
703 snp->cdb.DBaddr = (UINT64)(UINTN) &ConfigInfo;
\r
705 snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
\r
706 snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
\r
708 snp->cdb.IFnum = snp->if_num;
\r
709 snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
\r
711 DEBUG ((EFI_D_NET, "\nsnp->undi.get_config_info() "));
\r
713 (*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
\r
715 if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
\r
716 DEBUG ((EFI_D_NET, "\nsnp->undi.config_info() %xh:%xh\n", snp->cdb.StatFlags, snp->cdb.StatCode));
\r
718 goto Error_DeleteSNP;
\r
721 // Find the correct BAR to do IO.
\r
724 // Enumerate through the PCI BARs for the device to determine which one is
\r
725 // the IO BAR. Save the index of the BAR into the adapter info structure.
\r
726 // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped
\r
728 ConfigHeader = (PCI_TYPE00 *) &ConfigInfo.Config.Byte[0];
\r
729 TempBar = (UINT32 *) &ConfigHeader->Device.Bar[0];
\r
730 for (BarIndex = 0; BarIndex <= 5; BarIndex++) {
\r
731 if ((*TempBar & PCI_BAR_MEM_MASK) == PCI_BAR_MEM_64BIT) {
\r
733 // This is a 64-bit memory bar, skip this and the
\r
734 // next bar as well.
\r
739 if ((*TempBar & PCI_BAR_IO_MASK) == PCI_BAR_IO_MODE) {
\r
740 snp->IoBarIndex = BarIndex;
\r
748 // Initialize simple network protocol mode structure
\r
750 snp->mode.State = EfiSimpleNetworkStopped;
\r
751 snp->mode.HwAddressSize = snp->init_info.HWaddrLen;
\r
752 snp->mode.MediaHeaderSize = snp->init_info.MediaHeaderLen;
\r
753 snp->mode.MaxPacketSize = snp->init_info.FrameDataLen;
\r
754 snp->mode.NvRamAccessSize = snp->init_info.NvWidth;
\r
755 snp->mode.NvRamSize = snp->init_info.NvCount * snp->mode.NvRamAccessSize;
\r
756 snp->mode.IfType = snp->init_info.IFtype;
\r
757 snp->mode.MaxMCastFilterCount = snp->init_info.MCastFilterCnt;
\r
758 snp->mode.MCastFilterCount = 0;
\r
760 switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) {
\r
761 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED:
\r
762 snp->mode.MediaPresentSupported = TRUE;
\r
765 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED:
\r
767 snp->mode.MediaPresentSupported = FALSE;
\r
770 if ((pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) {
\r
771 snp->mode.MacAddressChangeable = TRUE;
\r
773 snp->mode.MacAddressChangeable = FALSE;
\r
776 if ((pxe->hw.Implementation & PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED) != 0) {
\r
777 snp->mode.MultipleTxSupported = TRUE;
\r
779 snp->mode.MultipleTxSupported = FALSE;
\r
782 snp->mode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
\r
784 if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) {
\r
785 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
\r
789 if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {
\r
790 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
\r
794 if ((pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {
\r
795 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
\r
799 if ((pxe->hw.Implementation & PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED) != 0) {
\r
800 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;
\r
804 if (pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) {
\r
805 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
\r
809 snp->mode.ReceiveFilterSetting = 0;
\r
812 // need to get the station address to save in the mode structure. we need to
\r
813 // initialize the UNDI first for this.
\r
815 snp->tx_rx_bufsize = snp->init_info.MemoryRequired;
\r
816 Status = pxe_init (snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE);
\r
820 goto Error_DeleteSNP;
\r
823 Status = pxe_get_stn_addr (snp);
\r
825 if (Status != EFI_SUCCESS) {
\r
826 DEBUG ((EFI_D_ERROR, "\nsnp->undi.get_station_addr() failed.\n"));
\r
827 pxe_shutdown (snp);
\r
829 goto Error_DeleteSNP;
\r
832 snp->mode.MediaPresent = FALSE;
\r
835 // We should not leave UNDI started and initialized here. this DriverStart()
\r
836 // routine must only find and attach the SNP interface to UNDI layer that it
\r
837 // finds on the given handle!
\r
838 // The UNDI layer will be started when upper layers call snp->start.
\r
839 // How ever, this DriverStart() must fill up the snp mode structure which
\r
840 // contains the MAC address of the NIC. For this reason we started and
\r
841 // initialized UNDI here, now we are done, do a shutdown and stop of the
\r
844 pxe_shutdown (snp);
\r
848 // add SNP to the undi handle
\r
850 Status = gBS->InstallProtocolInterface (
\r
852 &gEfiSimpleNetworkProtocolGuid,
\r
853 EFI_NATIVE_INTERFACE,
\r
857 if (!EFI_ERROR (Status)) {
\r
861 Status = mPciIoFncs->FreeBuffer (
\r
863 SNP_MEM_PAGES (4096),
\r
869 mPciIoFncs->FreeBuffer (
\r
871 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),
\r
875 gBS->CloseProtocol (
\r
877 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
\r
878 This->DriverBindingHandle,
\r
882 gBS->CloseProtocol (
\r
884 &gEfiDevicePathProtocolGuid,
\r
885 This->DriverBindingHandle,
\r
900 SimpleNetworkDriverStop (
\r
901 IN EFI_DRIVER_BINDING_PROTOCOL *This,
\r
902 IN EFI_HANDLE Controller,
\r
903 IN UINTN NumberOfChildren,
\r
904 IN EFI_HANDLE *ChildHandleBuffer
\r
908 EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol;
\r
912 // Get our context back.
\r
914 Status = gBS->OpenProtocol (
\r
916 &gEfiSimpleNetworkProtocolGuid,
\r
917 (VOID **) &SnpProtocol,
\r
918 This->DriverBindingHandle,
\r
920 EFI_OPEN_PROTOCOL_GET_PROTOCOL
\r
923 if (EFI_ERROR (Status)) {
\r
924 return EFI_UNSUPPORTED;
\r
927 Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol);
\r
929 Status = gBS->UninstallProtocolInterface (
\r
931 &gEfiSimpleNetworkProtocolGuid,
\r
935 if (EFI_ERROR (Status)) {
\r
939 Status = gBS->CloseProtocol (
\r
941 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
\r
942 This->DriverBindingHandle,
\r
946 Status = gBS->CloseProtocol (
\r
948 &gEfiDevicePathProtocolGuid,
\r
949 This->DriverBindingHandle,
\r
953 pxe_shutdown (Snp);
\r
956 mPciIoFncs->FreeBuffer (
\r
958 SNP_MEM_PAGES (4096),
\r
962 mPciIoFncs->FreeBuffer (
\r
964 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),
\r
973 Install all the driver protocol
\r
975 @param entry EFI_IMAGE_ENTRY_POINT)
\r
977 @retval EFI_SUCEESS Initialization routine has found UNDI hardware,
\r
978 loaded it's ROM, and installed a notify event for
\r
979 the Network Indentifier Interface Protocol
\r
981 @retval Other Return value from HandleProtocol for
\r
982 DeviceIoProtocol or LoadedImageProtocol
\r
987 InitializeSnpNiiDriver (
\r
988 IN EFI_HANDLE ImageHandle,
\r
989 IN EFI_SYSTEM_TABLE *SystemTable
\r
992 return EfiLibInstallDriverBindingComponentName2 (
\r
995 &mSimpleNetworkDriverBinding,
\r
997 &gSimpleNetworkComponentName,
\r
998 &gSimpleNetworkComponentName2
\r