X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FNetwork%2FSnpDxe%2FSnp.c;h=a23af05078bc8939c7ea42dc83f2d26ad9489888;hp=e01a135708bd2eab013fe67e79c06e875156aa45;hb=c0fd7f734e2d33e22215899b40a47b843129541d;hpb=0e549d5be531a840503445d38b4dad2315ef3413 diff --git a/MdeModulePkg/Universal/Network/SnpDxe/Snp.c b/MdeModulePkg/Universal/Network/SnpDxe/Snp.c index e01a135708..a23af05078 100644 --- a/MdeModulePkg/Universal/Network/SnpDxe/Snp.c +++ b/MdeModulePkg/Universal/Network/SnpDxe/Snp.c @@ -1,265 +1,57 @@ /** @file -Copyright (c) 2004 - 2005, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -Module name: - snp.c - -Abstract: + Implementation of driver entry point and driver binding protocol. +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "Snp.h" -EFI_STATUS -pxe_start ( - SNP_DRIVER *snp - ); -EFI_STATUS -pxe_stop ( - SNP_DRIVER *snp - ); -EFI_STATUS -pxe_init ( - SNP_DRIVER *snp, - UINT16 OpFlags - ); -EFI_STATUS -pxe_shutdown ( - SNP_DRIVER *snp - ); -EFI_STATUS -pxe_get_stn_addr ( - SNP_DRIVER *snp - ); - -EFI_STATUS -EFIAPI -InitializeSnpNiiDriver ( - IN EFI_HANDLE image_handle, - IN EFI_SYSTEM_TABLE *system_table - ); - -EFI_STATUS -EFIAPI -SimpleNetworkDriverSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -EFI_STATUS -EFIAPI -SimpleNetworkDriverStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -EFI_STATUS -EFIAPI -SimpleNetworkDriverStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ); - -// -// Simple Network Protocol Driver Global Variables -// -EFI_DRIVER_BINDING_PROTOCOL mSimpleNetworkDriverBinding = { - SimpleNetworkDriverSupported, - SimpleNetworkDriverStart, - SimpleNetworkDriverStop, - 0xa, - NULL, - NULL -}; - -// -// Module global variables needed to support undi 3.0 interface -// -EFI_PCI_IO_PROTOCOL *mPciIoFncs; -struct s_v2p *_v2p = NULL; // undi3.0 map_list head -// End Global variables -// - /** - This routine maps the given CPU address to a Device address. It creates a - an entry in the map list with the virtual and physical addresses and the - un map cookie. + One notified function to stop UNDI device when gBS->ExitBootServices() called. - @param v2p pointer to return a map list node pointer. - @param type the direction in which the data flows from the given - virtual address device->cpu or cpu->device or both - ways. - @param vaddr virtual address (or CPU address) to be mapped - @param bsize size of the buffer to be mapped. - - @retval EFI_SUCEESS routine has completed the mapping - @retval other error as indicated. + @param Event Pointer to this event + @param Context Event handler private data **/ -EFI_STATUS -add_v2p ( - IN OUT struct s_v2p **v2p, - EFI_PCI_IO_PROTOCOL_OPERATION type, - VOID *vaddr, - UINTN bsize - ) -{ - EFI_STATUS Status; - - if ((v2p == NULL) || (vaddr == NULL) || (bsize == 0)) { - return EFI_INVALID_PARAMETER; - } - - *v2p = AllocatePool (sizeof (struct s_v2p)); - if (*v2p != NULL) { - return EFI_OUT_OF_RESOURCES; - } - - Status = mPciIoFncs->Map ( - mPciIoFncs, - type, - vaddr, - &bsize, - &(*v2p)->paddr, - &(*v2p)->unmap - ); - if (Status != EFI_SUCCESS) { - FreePool (*v2p); - return Status; - } - (*v2p)->vaddr = vaddr; - (*v2p)->bsize = bsize; - (*v2p)->next = _v2p; - _v2p = *v2p; - - return EFI_SUCCESS; -} - - -/** - This routine searches the linked list of mapped address nodes (for undi3.0 - interface) to find the node that corresponds to the given virtual address and - returns a pointer to that node. - - @param v2p pointer to return a map list node pointer. - @param vaddr virtual address (or CPU address) to be searched in - the map list - - @retval EFI_SUCEESS if a match found! - @retval Other match not found - -**/ -EFI_STATUS -find_v2p ( - struct s_v2p **v2p, - VOID *vaddr +VOID +EFIAPI +SnpNotifyExitBootServices ( + EFI_EVENT Event, + VOID *Context ) { - struct s_v2p *v; - - if (v2p == NULL || vaddr == NULL) { - return EFI_INVALID_PARAMETER; - } + SNP_DRIVER *Snp; - for (v = _v2p; v != NULL; v = v->next) { - if (v->vaddr == vaddr) { - *v2p = v; - return EFI_SUCCESS; - } - } + Snp = (SNP_DRIVER *)Context; - return EFI_NOT_FOUND; + // + // Shutdown and stop UNDI driver + // + PxeShutdown (Snp); + PxeStop (Snp); } - /** - This routine unmaps the given virtual address and frees the memory allocated - for the map list node corresponding to that address. + Send command to UNDI. It does nothing currently. - @param vaddr virtual address (or CPU address) to be unmapped + @param Cdb command to be sent to UNDI. - @retval EFI_SUCEESS if successfully unmapped - @retval Other as indicated by the error + @retval EFI_INVALID_PARAMETER The command is 0. + @retval EFI_UNSUPPORTED Default return status because it's not + supported currently. **/ EFI_STATUS -del_v2p ( - VOID *vaddr - ) -{ - struct s_v2p *v; - struct s_v2p *t; - EFI_STATUS Status; - - if (vaddr == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (_v2p == NULL) { - return EFI_NOT_FOUND; - } - // - // Is our node at the head of the list?? - // - if ((v = _v2p)->vaddr == vaddr) { - _v2p = _v2p->next; - - Status = mPciIoFncs->Unmap (mPciIoFncs, v->unmap); - - FreePool (v); - - if (Status) { - DEBUG ((EFI_D_ERROR, "Unmap failed with status = %r\n", Status)); - } - return Status; - } - - for (; v->next != NULL; v = t) { - if ((t = v->next)->vaddr == vaddr) { - v->next = t->next; - Status = mPciIoFncs->Unmap (mPciIoFncs, t->unmap); - FreePool (t); - - if (Status) { - DEBUG ((EFI_D_ERROR, "Unmap failed with status = %r\n", Status)); - } - return Status; - } - } - - return EFI_NOT_FOUND; -} - -STATIC -EFI_STATUS -issue_hwundi_command ( - UINT64 cdb +EFIAPI +IssueHwUndiCommand ( + UINT64 Cdb ) -/*++ - -Routine Description: - -Arguments: - -Returns: - ---*/ { - DEBUG ((EFI_D_ERROR, "\nissue_hwundi_command() - This should not be called!")); + DEBUG ((EFI_D_ERROR, "\nIssueHwUndiCommand() - This should not be called!")); - if (cdb == 0) { + if (Cdb == 0) { return EFI_INVALID_PARAMETER; } @@ -273,49 +65,52 @@ Returns: /** Compute 8-bit checksum of a buffer. - @param ptr Pointer to buffer. - @param len Length of buffer in bytes. + @param Buffer Pointer to buffer. + @param Length Length of buffer in bytes. - @return 8-bit checksum of all bytes in buffer. - @return If ptr is NULL or len is zero, zero is returned. + @return 8-bit checksum of all bytes in buffer, or zero if ptr is NULL or len + is zero. **/ -STATIC UINT8 -calc_8bit_cksum ( - VOID *ptr, - UINTN len +Calc8BitCksum ( + VOID *Buffer, + UINTN Length ) { - UINT8 *bptr; - UINT8 cksum; + UINT8 *Ptr; + UINT8 Cksum; - bptr = ptr; - cksum = 0; + Ptr = Buffer; + Cksum = 0; - if (ptr == NULL || len == 0) { + if (Ptr == NULL || Length == 0) { return 0; } - while (len--) { - cksum = (UINT8) (cksum +*bptr++); + while (Length-- != 0) { + Cksum = (UINT8) (Cksum + *Ptr++); } - return cksum; + return Cksum; } - /** - Test to see if this driver supports Controller. Any Controller - that contains a Nii protocol can be supported. - - @param This Protocol instance pointer. - @param Controller Handle of device to test. - @param RemainingDevicePath Not used. - - @retval EFI_SUCCESS This driver supports this device. - @retval EFI_ALREADY_STARTED This driver is already running on this device. - @retval other This driver does not support this device. + Test to see if this driver supports ControllerHandle. This service + is called by the EFI boot service ConnectController(). In + order to make drivers as small as possible, there are a few calling + restrictions for this service. ConnectController() must + follow these calling restrictions. If any other agent wishes to call + Supported() it must also follow these calling restrictions. + + @param This Protocol instance pointer. + @param ControllerHandle Handle of device to test. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver supports this device. + @retval EFI_ALREADY_STARTED This driver is already running on this device. + @retval other This driver does not support this device. **/ EFI_STATUS @@ -328,7 +123,7 @@ SimpleNetworkDriverSupported ( { EFI_STATUS Status; EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NiiProtocol; - PXE_UNDI *pxe; + PXE_UNDI *Pxe; Status = gBS->OpenProtocol ( Controller, @@ -370,36 +165,36 @@ SimpleNetworkDriverSupported ( // // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required. // - if (NiiProtocol->ID & 0x0F) { + if ((NiiProtocol->Id & 0x0F) != 0) { DEBUG ((EFI_D_NET, "\n!PXE structure is not paragraph aligned.\n")); Status = EFI_UNSUPPORTED; goto Done; } - pxe = (PXE_UNDI *) (UINTN) (NiiProtocol->ID); + Pxe = (PXE_UNDI *) (UINTN) (NiiProtocol->Id); // // Verify !PXE revisions. // - if (pxe->hw.Signature != PXE_ROMID_SIGNATURE) { + if (Pxe->hw.Signature != PXE_ROMID_SIGNATURE) { DEBUG ((EFI_D_NET, "\n!PXE signature is not valid.\n")); Status = EFI_UNSUPPORTED; goto Done; } - if (pxe->hw.Rev < PXE_ROMID_REV) { + if (Pxe->hw.Rev < PXE_ROMID_REV) { DEBUG ((EFI_D_NET, "\n!PXE.Rev is not supported.\n")); Status = EFI_UNSUPPORTED; goto Done; } - if (pxe->hw.MajorVer < PXE_ROMID_MAJORVER) { + if (Pxe->hw.MajorVer < PXE_ROMID_MAJORVER) { DEBUG ((EFI_D_NET, "\n!PXE.MajorVer is not supported.\n")); Status = EFI_UNSUPPORTED; goto Done; - } else if (pxe->hw.MajorVer == PXE_ROMID_MAJORVER && pxe->hw.MinorVer < PXE_ROMID_MINORVER) { + } else if (Pxe->hw.MajorVer == PXE_ROMID_MAJORVER && Pxe->hw.MinorVer < PXE_ROMID_MINORVER) { DEBUG ((EFI_D_NET, "\n!PXE.MinorVer is not supported.")); Status = EFI_UNSUPPORTED; goto Done; @@ -407,14 +202,14 @@ SimpleNetworkDriverSupported ( // // Do S/W UNDI specific checks. // - if ((pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) == 0) { - if (pxe->sw.EntryPoint < pxe->sw.Len) { + if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) == 0) { + if (Pxe->sw.EntryPoint < Pxe->sw.Len) { DEBUG ((EFI_D_NET, "\n!PXE S/W entry point is not valid.")); Status = EFI_UNSUPPORTED; goto Done; } - if (pxe->sw.BusCnt == 0) { + if (Pxe->sw.BusCnt == 0) { DEBUG ((EFI_D_NET, "\n!PXE.BusCnt is zero.")); Status = EFI_UNSUPPORTED; goto Done; @@ -435,16 +230,22 @@ Done: return Status; } - /** - called for any handle that we said "supported" in the above call! + Start this driver on ControllerHandle. This service is called by the + EFI boot service ConnectController(). In order to make + drivers as small as possible, there are a few calling restrictions for + this service. ConnectController() must follow these + calling restrictions. If any other agent wishes to call Start() it + must also follow these calling restrictions. @param This Protocol instance pointer. - @param Controller Handle of device to start - @param RemainingDevicePath Not used. + @param ControllerHandle Handle of device to bind driver to. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. - @retval EFI_SUCCESS This driver supports this device. - @retval other This driver failed to start this device. + @retval EFI_SUCCESS This driver is added to ControllerHandle + @retval EFI_DEVICE_ERROR This driver could not be started due to a device error + @retval other This driver does not support this device **/ EFI_STATUS @@ -458,15 +259,16 @@ SimpleNetworkDriverStart ( EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii; EFI_DEVICE_PATH_PROTOCOL *NiiDevicePath; EFI_STATUS Status; - PXE_UNDI *pxe; - SNP_DRIVER *snp; - VOID *addr; + PXE_UNDI *Pxe; + SNP_DRIVER *Snp; + VOID *Address; EFI_HANDLE Handle; - PXE_PCI_CONFIG_INFO ConfigInfo; - PCI_TYPE00 *ConfigHeader; - UINT32 *TempBar; UINT8 BarIndex; PXE_STATFLAGS InitStatFlags; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc; + BOOLEAN FoundIoBar; + BOOLEAN FoundMemoryBar; DEBUG ((EFI_D_NET, "\nSnpNotifyNetworkInterfaceIdentifier() ")); @@ -496,7 +298,7 @@ SimpleNetworkDriverStart ( Status = gBS->OpenProtocol ( Handle, &gEfiPciIoProtocolGuid, - (VOID **) &mPciIoFncs, + (VOID **) &PciIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL @@ -527,18 +329,18 @@ SimpleNetworkDriverStart ( DEBUG ((EFI_D_INFO, "Start(): UNDI3.1 found\n")); - pxe = (PXE_UNDI *) (UINTN) (Nii->ID); + Pxe = (PXE_UNDI *) (UINTN) (Nii->Id); - if (calc_8bit_cksum (pxe, pxe->hw.Len) != 0) { + if (Calc8BitCksum (Pxe, Pxe->hw.Len) != 0) { DEBUG ((EFI_D_NET, "\n!PXE checksum is not correct.\n")); goto NiiError; } - if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) { + if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) { // // We can get any packets. // - } else if ((pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) { + } else if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) { // // We need to be able to get broadcast packets for DHCP. // If we do not have promiscuous support, we must at least have @@ -552,62 +354,75 @@ SimpleNetworkDriverStart ( // OK, we like this UNDI, and we know snp is not already there on this handle // Allocate and initialize a new simple network protocol structure. // - Status = mPciIoFncs->AllocateBuffer ( - mPciIoFncs, - AllocateAnyPages, - EfiBootServicesData, - SNP_MEM_PAGES (sizeof (SNP_DRIVER)), - &addr, - 0 - ); + Status = PciIo->AllocateBuffer ( + PciIo, + AllocateAnyPages, + EfiBootServicesData, + SNP_MEM_PAGES (sizeof (SNP_DRIVER)), + &Address, + 0 + ); if (Status != EFI_SUCCESS) { DEBUG ((EFI_D_NET, "\nCould not allocate SNP_DRIVER structure.\n")); goto NiiError; } - snp = (SNP_DRIVER *) (UINTN) addr; + Snp = (SNP_DRIVER *) (UINTN) Address; + + ZeroMem (Snp, sizeof (SNP_DRIVER)); - ZeroMem (snp, sizeof (SNP_DRIVER)); + Snp->PciIo = PciIo; + Snp->Signature = SNP_DRIVER_SIGNATURE; - snp->IoFncs = mPciIoFncs; - snp->Signature = SNP_DRIVER_SIGNATURE; + EfiInitializeLock (&Snp->Lock, TPL_NOTIFY); - EfiInitializeLock (&snp->lock, TPL_NOTIFY); + Snp->Snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION; + Snp->Snp.Start = SnpUndi32Start; + Snp->Snp.Stop = SnpUndi32Stop; + Snp->Snp.Initialize = SnpUndi32Initialize; + Snp->Snp.Reset = SnpUndi32Reset; + Snp->Snp.Shutdown = SnpUndi32Shutdown; + Snp->Snp.ReceiveFilters = SnpUndi32ReceiveFilters; + Snp->Snp.StationAddress = SnpUndi32StationAddress; + Snp->Snp.Statistics = SnpUndi32Statistics; + Snp->Snp.MCastIpToMac = SnpUndi32McastIpToMac; + Snp->Snp.NvData = SnpUndi32NvData; + Snp->Snp.GetStatus = SnpUndi32GetStatus; + Snp->Snp.Transmit = SnpUndi32Transmit; + Snp->Snp.Receive = SnpUndi32Receive; + Snp->Snp.WaitForPacket = NULL; - snp->snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION; - snp->snp.Start = snp_undi32_start; - snp->snp.Stop = snp_undi32_stop; - snp->snp.Initialize = snp_undi32_initialize; - snp->snp.Reset = snp_undi32_reset; - snp->snp.Shutdown = snp_undi32_shutdown; - snp->snp.ReceiveFilters = snp_undi32_receive_filters; - snp->snp.StationAddress = snp_undi32_station_address; - snp->snp.Statistics = snp_undi32_statistics; - snp->snp.MCastIpToMac = snp_undi32_mcast_ip_to_mac; - snp->snp.NvData = snp_undi32_nvdata; - snp->snp.GetStatus = snp_undi32_get_status; - snp->snp.Transmit = snp_undi32_transmit; - snp->snp.Receive = snp_undi32_receive; - snp->snp.WaitForPacket = NULL; + Snp->Snp.Mode = &Snp->Mode; - snp->snp.Mode = &snp->mode; + Snp->TxRxBufferSize = 0; + Snp->TxRxBuffer = NULL; + + Snp->RecycledTxBuf = AllocatePool (sizeof (UINT64) * SNP_TX_BUFFER_INCREASEMENT); + if (Snp->RecycledTxBuf == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error_DeleteSNP; + } + Snp->MaxRecycledTxBuf = SNP_TX_BUFFER_INCREASEMENT; + Snp->RecycledTxBufCount = 0; - snp->tx_rx_bufsize = 0; - snp->tx_rx_buffer = NULL; + if (Nii->Revision >= EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION) { + Snp->IfNum = Nii->IfNum; - snp->if_num = Nii->IfNum; + } else { + Snp->IfNum = (UINT8) (Nii->IfNum & 0xFF); + } - if ((pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) { - snp->is_swundi = FALSE; - snp->issue_undi32_command = &issue_hwundi_command; + if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) { + Snp->IsSwUndi = FALSE; + Snp->IssueUndi32Command = &IssueHwUndiCommand; } else { - snp->is_swundi = TRUE; + Snp->IsSwUndi = TRUE; - if ((pxe->sw.Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR) != 0) { - snp->issue_undi32_command = (issue_undi32_command) (UINTN) pxe->sw.EntryPoint; + if ((Pxe->sw.Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR) != 0) { + Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) Pxe->sw.EntryPoint; } else { - snp->issue_undi32_command = (issue_undi32_command) (UINTN) ((UINT8) (UINTN) pxe + pxe->sw.EntryPoint); + Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) ((UINT8) (UINTN) Pxe + Pxe->sw.EntryPoint); } } // @@ -626,223 +441,226 @@ SimpleNetworkDriverStart ( // -it is OK to allocate one global set of CPB, DB pair for each UNDI // interface as EFI does not multi-task and so SNP will not be re-entered! // - Status = mPciIoFncs->AllocateBuffer ( - mPciIoFncs, - AllocateAnyPages, - EfiBootServicesData, - SNP_MEM_PAGES (4096), - &addr, - 0 - ); + Status = PciIo->AllocateBuffer ( + PciIo, + AllocateAnyPages, + EfiBootServicesData, + SNP_MEM_PAGES (4096), + &Address, + 0 + ); if (Status != EFI_SUCCESS) { DEBUG ((EFI_D_NET, "\nCould not allocate CPB and DB structures.\n")); goto Error_DeleteSNP; } - snp->cpb = (VOID *) (UINTN) addr; - snp->db = (VOID *) ((UINTN) addr + 2048); - - // - // pxe_start call is going to give the callback functions to UNDI, these callback - // functions use the BarIndex values from the snp structure, so these must be initialized - // with default values before doing a pxe_start. The correct values can be obtained after - // getting the config information from UNDI - // - snp->MemoryBarIndex = 0; - snp->IoBarIndex = 1; + Snp->Cpb = (VOID *) (UINTN) Address; + Snp->Db = (VOID *) ((UINTN) Address + 2048); // - // we need the undi init information many times in this snp code, just get it - // once here and store it in the snp driver structure. to get Init Info - // from UNDI we have to start undi first. + // Find the correct BAR to do IO. // - Status = pxe_start (snp); - - if (Status != EFI_SUCCESS) { - goto Error_DeleteSNP; - } - - snp->cdb.OpCode = PXE_OPCODE_GET_INIT_INFO; - snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED; - - snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED; - snp->cdb.CPBaddr = PXE_DBADDR_NOT_USED; - - snp->cdb.DBsize = sizeof snp->init_info; - snp->cdb.DBaddr = (UINT64)(UINTN) &snp->init_info; - - snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; - snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + // Enumerate through the PCI BARs for the device to determine which one is + // the IO BAR. Save the index of the BAR into the adapter info structure. + // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped + // + Snp->MemoryBarIndex = 0; + Snp->IoBarIndex = 1; + FoundMemoryBar = FALSE; + FoundIoBar = FALSE; + for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) { + Status = PciIo->GetBarAttributes ( + PciIo, + BarIndex, + NULL, + (VOID**) &BarDesc + ); + if (Status == EFI_UNSUPPORTED) { + continue; + } else if (EFI_ERROR (Status)) { + goto Error_DeleteSNP; + } - snp->cdb.IFnum = snp->if_num; - snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + if ((!FoundMemoryBar) && (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM)) { + Snp->MemoryBarIndex = BarIndex; + FoundMemoryBar = TRUE; + } else if ((!FoundIoBar) && (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_IO)) { + Snp->IoBarIndex = BarIndex; + FoundIoBar = TRUE; + } - DEBUG ((EFI_D_NET, "\nsnp->undi.get_init_info() ")); + FreePool (BarDesc); - (*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb); + if (FoundMemoryBar && FoundIoBar) { + break; + } + } - // - // Save the INIT Stat Code... - // - InitStatFlags = snp->cdb.StatFlags; + Status = PxeStart (Snp); - if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) { - DEBUG ((EFI_D_NET, "\nsnp->undi.init_info() %xh:%xh\n", snp->cdb.StatFlags, snp->cdb.StatCode)); - pxe_stop (snp); + if (Status != EFI_SUCCESS) { goto Error_DeleteSNP; } - snp->cdb.OpCode = PXE_OPCODE_GET_CONFIG_INFO; - snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED; + Snp->Cdb.OpCode = PXE_OPCODE_GET_INIT_INFO; + Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED; - snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED; - snp->cdb.CPBaddr = PXE_DBADDR_NOT_USED; + Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED; + Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED; - snp->cdb.DBsize = sizeof ConfigInfo; - snp->cdb.DBaddr = (UINT64)(UINTN) &ConfigInfo; + Snp->Cdb.DBsize = (UINT16) sizeof (Snp->InitInfo); + Snp->Cdb.DBaddr = (UINT64)(UINTN) (&Snp->InitInfo); - snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; - snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE; + Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; - snp->cdb.IFnum = snp->if_num; - snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + Snp->Cdb.IFnum = Snp->IfNum; + Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; - DEBUG ((EFI_D_NET, "\nsnp->undi.get_config_info() ")); + DEBUG ((EFI_D_NET, "\nSnp->undi.get_init_info() ")); - (*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb); + (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb); - if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) { - DEBUG ((EFI_D_NET, "\nsnp->undi.config_info() %xh:%xh\n", snp->cdb.StatFlags, snp->cdb.StatCode)); - pxe_stop (snp); - goto Error_DeleteSNP; - } - // - // Find the correct BAR to do IO. // + // Save the INIT Stat Code... // - // Enumerate through the PCI BARs for the device to determine which one is - // the IO BAR. Save the index of the BAR into the adapter info structure. - // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped - // - ConfigHeader = (PCI_TYPE00 *) &ConfigInfo.Config.Byte[0]; - TempBar = (UINT32 *) &ConfigHeader->Device.Bar[0]; - for (BarIndex = 0; BarIndex <= 5; BarIndex++) { - if ((*TempBar & PCI_BAR_MEM_MASK) == PCI_BAR_MEM_64BIT) { - // - // This is a 64-bit memory bar, skip this and the - // next bar as well. - // - TempBar++; - } + InitStatFlags = Snp->Cdb.StatFlags; - if ((*TempBar & PCI_BAR_IO_MASK) == PCI_BAR_IO_MODE) { - snp->IoBarIndex = BarIndex; - break; - } - - TempBar++; + if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) { + DEBUG ((EFI_D_NET, "\nSnp->undi.init_info() %xh:%xh\n", Snp->Cdb.StatFlags, Snp->Cdb.StatCode)); + PxeStop (Snp); + goto Error_DeleteSNP; } // // Initialize simple network protocol mode structure // - snp->mode.State = EfiSimpleNetworkStopped; - snp->mode.HwAddressSize = snp->init_info.HWaddrLen; - snp->mode.MediaHeaderSize = snp->init_info.MediaHeaderLen; - snp->mode.MaxPacketSize = snp->init_info.FrameDataLen; - snp->mode.NvRamAccessSize = snp->init_info.NvWidth; - snp->mode.NvRamSize = snp->init_info.NvCount * snp->mode.NvRamAccessSize; - snp->mode.IfType = snp->init_info.IFtype; - snp->mode.MaxMCastFilterCount = snp->init_info.MCastFilterCnt; - snp->mode.MCastFilterCount = 0; + Snp->Mode.State = EfiSimpleNetworkStopped; + Snp->Mode.HwAddressSize = Snp->InitInfo.HWaddrLen; + Snp->Mode.MediaHeaderSize = Snp->InitInfo.MediaHeaderLen; + Snp->Mode.MaxPacketSize = Snp->InitInfo.FrameDataLen; + Snp->Mode.NvRamAccessSize = Snp->InitInfo.NvWidth; + Snp->Mode.NvRamSize = Snp->InitInfo.NvCount * Snp->Mode.NvRamAccessSize; + Snp->Mode.IfType = Snp->InitInfo.IFtype; + Snp->Mode.MaxMCastFilterCount = Snp->InitInfo.MCastFilterCnt; + Snp->Mode.MCastFilterCount = 0; switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) { case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED: - snp->mode.MediaPresentSupported = TRUE; + Snp->CableDetectSupported = TRUE; break; case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED: default: - snp->mode.MediaPresentSupported = FALSE; + Snp->CableDetectSupported = FALSE; + } + + switch (InitStatFlags & PXE_STATFLAGS_GET_STATUS_NO_MEDIA_MASK) { + case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED: + Snp->MediaStatusSupported = TRUE; + break; + + case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_NOT_SUPPORTED: + default: + Snp->MediaStatusSupported = FALSE; + } + + if (Snp->CableDetectSupported || Snp->MediaStatusSupported) { + Snp->Mode.MediaPresentSupported = TRUE; } - if ((pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) { - snp->mode.MacAddressChangeable = TRUE; + if ((Pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) { + Snp->Mode.MacAddressChangeable = TRUE; } else { - snp->mode.MacAddressChangeable = FALSE; + Snp->Mode.MacAddressChangeable = FALSE; } - if ((pxe->hw.Implementation & PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED) != 0) { - snp->mode.MultipleTxSupported = TRUE; + if ((Pxe->hw.Implementation & PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED) != 0) { + Snp->Mode.MultipleTxSupported = TRUE; } else { - snp->mode.MultipleTxSupported = FALSE; + Snp->Mode.MultipleTxSupported = FALSE; } - snp->mode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST; + Snp->Mode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST; - if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) { - snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; + if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) { + Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; } - if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) { - snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS; + if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) { + Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS; } - if ((pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) { - snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST; + if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) { + Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST; } - if ((pxe->hw.Implementation & PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED) != 0) { - snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST; + if ((Pxe->hw.Implementation & PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED) != 0) { + Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST; } - if (pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) { - snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; + if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) { + Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; } - snp->mode.ReceiveFilterSetting = 0; + Snp->Mode.ReceiveFilterSetting = 0; // // need to get the station address to save in the mode structure. we need to // initialize the UNDI first for this. // - snp->tx_rx_bufsize = snp->init_info.MemoryRequired; - Status = pxe_init (snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE); + Snp->TxRxBufferSize = Snp->InitInfo.MemoryRequired; + Status = PxeInit (Snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE); - if (Status) { - pxe_stop (snp); + if (EFI_ERROR (Status)) { + PxeStop (Snp); goto Error_DeleteSNP; } - Status = pxe_get_stn_addr (snp); + Status = PxeGetStnAddr (Snp); if (Status != EFI_SUCCESS) { - DEBUG ((EFI_D_ERROR, "\nsnp->undi.get_station_addr() failed.\n")); - pxe_shutdown (snp); - pxe_stop (snp); + DEBUG ((EFI_D_ERROR, "\nSnp->undi.get_station_addr() failed.\n")); + PxeShutdown (Snp); + PxeStop (Snp); goto Error_DeleteSNP; } - snp->mode.MediaPresent = FALSE; + Snp->Mode.MediaPresent = FALSE; // // We should not leave UNDI started and initialized here. this DriverStart() // routine must only find and attach the SNP interface to UNDI layer that it // finds on the given handle! - // The UNDI layer will be started when upper layers call snp->start. + // The UNDI layer will be started when upper layers call Snp->start. // How ever, this DriverStart() must fill up the snp mode structure which // contains the MAC address of the NIC. For this reason we started and // initialized UNDI here, now we are done, do a shutdown and stop of the // UNDI interface! // - pxe_shutdown (snp); - pxe_stop (snp); + PxeShutdown (Snp); + PxeStop (Snp); + + // + // Create EXIT_BOOT_SERIVES Event + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + SnpNotifyExitBootServices, + Snp, + &gEfiEventExitBootServicesGuid, + &Snp->ExitBootServicesEvent + ); + if (EFI_ERROR (Status)) { + goto Error_DeleteSNP; + } // // add SNP to the undi handle @@ -851,26 +669,30 @@ SimpleNetworkDriverStart ( &Controller, &gEfiSimpleNetworkProtocolGuid, EFI_NATIVE_INTERFACE, - &(snp->snp) + &(Snp->Snp) ); if (!EFI_ERROR (Status)) { return Status; } - Status = mPciIoFncs->FreeBuffer ( - mPciIoFncs, - SNP_MEM_PAGES (4096), - snp->cpb - ); + PciIo->FreeBuffer ( + PciIo, + SNP_MEM_PAGES (4096), + Snp->Cpb + ); Error_DeleteSNP: - mPciIoFncs->FreeBuffer ( - mPciIoFncs, - SNP_MEM_PAGES (sizeof (SNP_DRIVER)), - snp - ); + if (Snp->RecycledTxBuf != NULL) { + FreePool (Snp->RecycledTxBuf); + } + + PciIo->FreeBuffer ( + PciIo, + SNP_MEM_PAGES (sizeof (SNP_DRIVER)), + Snp + ); NiiError: gBS->CloseProtocol ( Controller, @@ -886,13 +708,32 @@ NiiError: Controller ); + // + // If we got here that means we are in error state. + // + if (!EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + } + return Status; } - /** - - + Stop this driver on ControllerHandle. This service is called by the + EFI boot service DisconnectController(). In order to + make drivers as small as possible, there are a few calling + restrictions for this service. DisconnectController() + must follow these calling restrictions. If any other agent wishes + to call Stop() it must also follow these calling restrictions. + + @param This Protocol instance pointer. + @param ControllerHandle Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed ControllerHandle + @retval other This driver was not removed from this device **/ EFI_STATUS @@ -907,6 +748,7 @@ SimpleNetworkDriverStop ( EFI_STATUS Status; EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol; SNP_DRIVER *Snp; + EFI_PCI_IO_PROTOCOL *PciIo; // // Get our context back. @@ -929,13 +771,18 @@ SimpleNetworkDriverStop ( Status = gBS->UninstallProtocolInterface ( Controller, &gEfiSimpleNetworkProtocolGuid, - &Snp->snp + &Snp->Snp ); if (EFI_ERROR (Status)) { return Status; } + // + // Close EXIT_BOOT_SERIVES Event + // + gBS->CloseEvent (Snp->ExitBootServicesEvent); + Status = gBS->CloseProtocol ( Controller, &gEfiNetworkInterfaceIdentifierProtocolGuid_31, @@ -950,36 +797,51 @@ SimpleNetworkDriverStop ( Controller ); - pxe_shutdown (Snp); - pxe_stop (Snp); + PxeShutdown (Snp); + PxeStop (Snp); - mPciIoFncs->FreeBuffer ( - mPciIoFncs, - SNP_MEM_PAGES (4096), - Snp->cpb - ); + FreePool (Snp->RecycledTxBuf); - mPciIoFncs->FreeBuffer ( - mPciIoFncs, - SNP_MEM_PAGES (sizeof (SNP_DRIVER)), - Snp - ); + PciIo = Snp->PciIo; + PciIo->FreeBuffer ( + PciIo, + SNP_MEM_PAGES (4096), + Snp->Cpb + ); + + PciIo->FreeBuffer ( + PciIo, + SNP_MEM_PAGES (sizeof (SNP_DRIVER)), + Snp + ); return Status; } +// +// Simple Network Protocol Driver Global Variables +// +EFI_DRIVER_BINDING_PROTOCOL gSimpleNetworkDriverBinding = { + SimpleNetworkDriverSupported, + SimpleNetworkDriverStart, + SimpleNetworkDriverStop, + 0xa, + NULL, + NULL +}; /** - Install all the driver protocol + The SNP driver entry point. - @param entry EFI_IMAGE_ENTRY_POINT) + @param ImageHandle The driver image handle. + @param SystemTable The system table. - @retval EFI_SUCEESS Initialization routine has found UNDI hardware, - loaded it's ROM, and installed a notify event for - the Network Indentifier Interface Protocol - successfully. - @retval Other Return value from HandleProtocol for - DeviceIoProtocol or LoadedImageProtocol + @retval EFI_SUCEESS Initialization routine has found UNDI hardware, + loaded it's ROM, and installed a notify event for + the Network Indentifier Interface Protocol + successfully. + @retval Other Return value from HandleProtocol for + DeviceIoProtocol or LoadedImageProtocol **/ EFI_STATUS @@ -992,8 +854,8 @@ InitializeSnpNiiDriver ( return EfiLibInstallDriverBindingComponentName2 ( ImageHandle, SystemTable, - &mSimpleNetworkDriverBinding, - NULL, + &gSimpleNetworkDriverBinding, + ImageHandle, &gSimpleNetworkComponentName, &gSimpleNetworkComponentName2 );