VOID EFIAPI VirtioNetIsPacketAvailable ( IN EFI_EVENT Event, IN VOID *Context ) { // // This callback has been enqueued by an external application and is // running at TPL_CALLBACK already. // // The WaitForPacket logic is similar to that of WaitForKey. The former has // almost no documentation in either the UEFI-2.3.1+errC spec or the // DWG-2.3.1, but WaitForKey does have some. // VNET_DEV *Dev; UINT16 RxCurUsed; Dev = Context; if (Dev->Snm.State != EfiSimpleNetworkInitialized) { return; } // // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device // MemoryFence (); RxCurUsed = *Dev->RxRing.Used.Idx; MemoryFence (); if (Dev->RxLastUsed != RxCurUsed) { gBS->SignalEvent (&Dev->Snp.WaitForPacket); } }
/** Override function for SDHCI controller operations @param[in] ControllerHandle The EFI_HANDLE of the controller. @param[in] Slot The 0 based slot index. @param[in] PhaseType The type of operation and whether the hook is invoked right before (pre) or right after (post) @retval EFI_SUCCESS The override function completed successfully. @retval EFI_NOT_FOUND The specified controller or slot does not exist. @retval EFI_INVALID_PARAMETER PhaseType is invalid **/ STATIC EFI_STATUS EFIAPI SynQuacerSdMmcNotifyPhase ( IN EFI_HANDLE ControllerHandle, IN UINT8 Slot, IN EDKII_SD_MMC_PHASE_TYPE PhaseType ) { if (ControllerHandle != mSdMmcControllerHandle) { return EFI_SUCCESS; } ASSERT (Slot == 0); switch (PhaseType) { case EdkiiSdMmcResetPre: // Soft reset does not complete unless the clock is already enabled. MmioWrite16 (SYNQUACER_EMMC_BASE + SD_HC_CLOCK_CTRL, SYNQUACER_CLOCK_CTRL_VAL); break; case EdkiiSdMmcInitHostPre: // init vendor specific regs MmioAnd16 (SYNQUACER_EMMC_BASE + F_SDH30_AHB_CONFIG, ~(F_SDH30_AHB_BIGED | F_SDH30_BUSLOCK_EN)); MmioOr16 (SYNQUACER_EMMC_BASE + F_SDH30_AHB_CONFIG, F_SDH30_SIN | F_SDH30_AHB_INCR_16 | F_SDH30_AHB_INCR_8 | F_SDH30_AHB_INCR_4); MmioAnd32 (SYNQUACER_EMMC_BASE + F_SDH30_ESD_CONTROL, ~F_SDH30_EMMC_RST); MemoryFence (); gBS->Stall (ESD_CONTROL_RESET_DELAY); MmioOr32 (SYNQUACER_EMMC_BASE + F_SDH30_ESD_CONTROL, F_SDH30_EMMC_RST | F_SDH30_CMD_DAT_DELAY | F_SDH30_EMMC_HS200); gBS->Stall (IO_CONTROL2_SETTLE_US); MmioOr32 (SYNQUACER_EMMC_BASE + F_SDH30_IO_CONTROL2, F_SDH30_CRES_O_DN); MemoryFence (); MmioOr32 (SYNQUACER_EMMC_BASE + F_SDH30_IO_CONTROL2, F_SDH30_MSEL_O_1_8); MemoryFence (); MmioAnd32 (SYNQUACER_EMMC_BASE + F_SDH30_IO_CONTROL2, ~F_SDH30_CRES_O_DN); MemoryFence (); gBS->Stall (IO_CONTROL2_SETTLE_US); MmioOr32 (SYNQUACER_EMMC_BASE + F_SDH30_TUNING_SETTING, F_SDH30_CMD_CHK_DIS); break; default: break; } return EFI_SUCCESS; }
/** Notify the host about appended descriptors and wait until it processes the last one (ie. all of them). @param[in] PciIo The target virtio PCI device to notify. @param[in] VirtQueueId Identifies the queue for the target device. @param[in out] Ring The virtio ring with descriptors to submit. @param[in] Indices The function waits until the host processes descriptors up to Indices->NextAvailIdx. @return Error code from VirtioWrite() if it fails. @retval EFI_SUCCESS Otherwise, the host processed all descriptors. **/ EFI_STATUS EFIAPI VirtioFlush ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT16 VirtQueueId, IN OUT VRING *Ring, IN DESC_INDICES *Indices ) { EFI_STATUS Status; UINTN PollPeriodUsecs; // // virtio-0.9.5, 2.4.1.3 Updating the Index Field // MemoryFence(); *Ring->Avail.Idx = Indices->NextAvailIdx; // // virtio-0.9.5, 2.4.1.4 Notifying the Device -- gratuitous notifications are // OK. // MemoryFence(); Status = VirtioWrite ( PciIo, OFFSET_OF (VIRTIO_HDR, VhdrQueueNotify), sizeof (UINT16), VirtQueueId ); if (EFI_ERROR (Status)) { return Status; } // // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device // Wait until the host processes and acknowledges our descriptor chain. The // condition we use for polling is greatly simplified and relies on the // synchronous, lock-step progress. // // Keep slowing down until we reach a poll period of slightly above 1 ms. // PollPeriodUsecs = 1; MemoryFence(); while (*Ring->Used.Idx != Indices->NextAvailIdx) { gBS->Stall (PollPeriodUsecs); // calls AcpiTimerLib::MicroSecondDelay if (PollPeriodUsecs < 1024) { PollPeriodUsecs *= 2; } MemoryFence(); } return EFI_SUCCESS; }
/** Writes an 8-bit MMIO register. Writes the 8-bit MMIO register specified by Address with the value specified by Value and returns Value. This function must guarantee that all MMIO read and write operations are serialized. If 8-bit MMIO register operations are not supported, then ASSERT(). @param Address The MMIO register to write. @param Value The value to write to the MMIO register. @return Value. **/ UINT8 EFIAPI MmioWrite8 ( IN UINTN Address, IN UINT8 Value ) { MemoryFence (); *(volatile UINT8*)Address = Value; MemoryFence (); return Value; }
/** Reads an 8-bit MMIO register. Reads the 8-bit MMIO register specified by Address. The 8-bit read value is returned. This function must guarantee that all MMIO read and write operations are serialized. If 8-bit MMIO register operations are not supported, then ASSERT(). @param Address The MMIO register to read. @return The value read. **/ UINT8 EFIAPI MmioRead8 ( IN UINTN Address ) { UINT8 Value; MemoryFence (); Value = *(volatile UINT8*)Address; MemoryFence (); return Value; }
/** Writes a 64-bit MMIO register. Writes the 64-bit MMIO register specified by Address with the value specified by Value and returns Value. This function must guarantee that all MMIO read and write operations are serialized. @param Address The MMIO register to write. @param Data The value to write to the MMIO register. @return The value written the memory address. **/ UINT64 EFIAPI MmioWrite64 ( IN UINT64 Address, IN UINT64 Data ) { Address |= BIT63; MemoryFence (); *((volatile UINT64 *) Address) = Data; MemoryFence (); return Data; }
/** Writes a 16-bit MMIO register. Writes the 16-bit MMIO register specified by Address with the value specified by Value and returns Value. This function must guarantee that all MMIO read and write operations are serialized. If 16-bit MMIO register operations are not supported, then ASSERT(). If Address is not aligned on a 16-bit boundary, then ASSERT(). @param Address The MMIO register to write. @param Value The value to write to the MMIO register. @return Value. **/ UINT16 EFIAPI MmioWrite16 ( IN UINTN Address, IN UINT16 Value ) { ASSERT ((Address & 1) == 0); MemoryFence (); *(volatile UINT16*)Address = Value; MemoryFence (); return Value; }
/** Writes a 64-bit MMIO register. Writes the 64-bit MMIO register specified by Address with the value specified by Value and returns Value. This function must guarantee that all MMIO read and write operations are serialized. If 64-bit MMIO register operations are not supported, then ASSERT(). If Address is not aligned on a 64-bit boundary, then ASSERT(). @param Address The MMIO register to write. @param Value The value to write to the MMIO register. **/ UINT64 EFIAPI MmioWrite64 ( IN UINTN Address, IN UINT64 Value ) { ASSERT ((Address & 7) == 0); MemoryFence (); *(volatile UINT64*)Address = Value; MemoryFence (); return Value; }
/** Writes a 32-bit MMIO register. Writes the 32-bit MMIO register specified by Address with the value specified by Value and returns Value. This function must guarantee that all MMIO read and write operations are serialized. If 32-bit MMIO register operations are not supported, then ASSERT(). If Address is not aligned on a 32-bit boundary, then ASSERT(). @param Address The MMIO register to write. @param Value The value to write to the MMIO register. @return Value. **/ UINT32 EFIAPI MmioWrite32 ( IN UINTN Address, IN UINT32 Value ) { ASSERT ((Address & 3) == 0); MemoryFence (); *(volatile UINT32*)Address = Value; MemoryFence (); return Value; }
/** Reads a 8-bit MMIO register. Reads the 8-bit MMIO register specified by Address. The 8-bit read value is returned. This function must guarantee that all MMIO read and write operations are serialized. @param Address The MMIO register to read. @return The value read. **/ UINT8 EFIAPI MmioRead8 ( IN UINT64 Address ) { UINT8 Data; Address |= BIT63; MemoryFence (); Data = *((volatile UINT8 *) Address); MemoryFence (); return Data; }
/** Reads a 16-bit MMIO register. Reads the 16-bit MMIO register specified by Address. The 16-bit read value is returned. This function must guarantee that all MMIO read and write operations are serialized. @param Address The MMIO register to read. @return The value read. **/ UINT16 EFIAPI MmioRead16 ( IN UINT64 Address ) { UINT16 Data; Address |= BIT63; MemoryFence (); Data = *((volatile UINT16 *) Address); MemoryFence (); return Data; }
/** Write to a local APIC register. This function writes to a local APIC register either in xAPIC or x2APIC mode. It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be accessed using multiple 32-bit loads or stores, so this function only performs 32-bit write. if the register index is invalid or unsupported in current APIC mode, then ASSERT. @param MmioOffset The MMIO offset of the local APIC register in xAPIC mode. It must be 16-byte aligned. @param Value Value to be written to the register. **/ VOID EFIAPI WriteLocalApicReg ( IN UINTN MmioOffset, IN UINT32 Value ) { UINT32 MsrIndex; ASSERT ((MmioOffset & 0xf) == 0); if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) { MmioWrite32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + MmioOffset, Value); } else { // // DFR is not supported in x2APIC mode. // ASSERT (MmioOffset != XAPIC_ICR_DFR_OFFSET); // // Note that in x2APIC mode, ICR is a 64-bit MSR that needs special treatment. It // is not supported in this function for simplicity. // ASSERT (MmioOffset != XAPIC_ICR_HIGH_OFFSET); ASSERT (MmioOffset != XAPIC_ICR_LOW_OFFSET); MsrIndex = (UINT32)(MmioOffset >> 4) + X2APIC_MSR_BASE_ADDRESS; // // The serializing semantics of WRMSR are relaxed when writing to the APIC registers. // Use memory fence here to force the serializing semantics to be consisent with xAPIC mode. // MemoryFence (); AsmWriteMsr32 (MsrIndex, Value); } }
/** Reads a 32-bit MMIO register. Reads the 32-bit MMIO register specified by Address. The 32-bit read value is returned. This function must guarantee that all MMIO read and write operations are serialized. @param Address The MMIO register to read. @return The value read. **/ UINT32 EFIAPI MmioRead32 ( IN UINT64 Address ) { UINT32 Data; Address |= BIT63; MemoryFence (); Data = *((volatile UINT32 *) Address); MemoryFence (); return Data; }
/** Reads a 16-bit MMIO register. Reads the 16-bit MMIO register specified by Address. The 16-bit read value is returned. This function must guarantee that all MMIO read and write operations are serialized. If 16-bit MMIO register operations are not supported, then ASSERT(). If Address is not aligned on a 16-bit boundary, then ASSERT(). @param Address The MMIO register to read. @return The value read. **/ UINT16 EFIAPI MmioRead16 ( IN UINTN Address ) { UINT16 Value; ASSERT ((Address & 1) == 0); MemoryFence (); Value = *(volatile UINT16*)Address; MemoryFence (); return Value; }
/** Reads a 64-bit MMIO register. Reads the 64-bit MMIO register specified by Address. The 64-bit read value is returned. This function must guarantee that all MMIO read and write operations are serialized. If 64-bit MMIO register operations are not supported, then ASSERT(). If Address is not aligned on a 64-bit boundary, then ASSERT(). @param Address The MMIO register to read. @return The value read. **/ UINT64 EFIAPI MmioRead64 ( IN UINTN Address ) { UINT64 Value; ASSERT ((Address & 7) == 0); MemoryFence (); Value = *(volatile UINT64*)Address; MemoryFence (); return Value; }
/** Reads a 32-bit MMIO register. Reads the 32-bit MMIO register specified by Address. The 32-bit read value is returned. This function must guarantee that all MMIO read and write operations are serialized. If 32-bit MMIO register operations are not supported, then ASSERT(). If Address is not aligned on a 32-bit boundary, then ASSERT(). @param Address The MMIO register to read. @return The value read. **/ UINT32 EFIAPI MmioRead32 ( IN UINTN Address ) { UINT32 Value; ASSERT ((Address & 3) == 0); MemoryFence (); Value = *(volatile UINT32*)Address; MemoryFence (); return Value; }
/*++ Name: RingBufferRead() Description: Read and advance the read index --*/ int RingBufferRead( RING_BUFFER_INFO* InRingInfo, PVOID Buffer, UINT32 BufferLen, UINT32 Offset ) { UINT32 bytesAvailToWrite; UINT32 bytesAvailToRead; UINT32 nextReadLocation=0; UINT64 prevIndices=0; ASSERT(BufferLen > 0); SpinlockAcquire(InRingInfo->RingLock); GetRingBufferAvailBytes(InRingInfo, &bytesAvailToRead, &bytesAvailToWrite); DPRINT_DBG(VMBUS, "Reading %u bytes...", BufferLen); //DumpRingInfo(InRingInfo, "BEFORE "); // Make sure there is something to read if (bytesAvailToRead < BufferLen ) { DPRINT_DBG(VMBUS, "got callback but not enough to read <avail to read %d read size %d>!!", bytesAvailToRead, BufferLen); SpinlockRelease(InRingInfo->RingLock); return -1; } nextReadLocation = GetNextReadLocationWithOffset(InRingInfo, Offset); nextReadLocation = CopyFromRingBuffer(InRingInfo, Buffer, BufferLen, nextReadLocation); nextReadLocation = CopyFromRingBuffer(InRingInfo, &prevIndices, sizeof(UINT64), nextReadLocation); // Make sure all reads are done before we update the read index since // the writer may start writing to the read area once the read index is updated MemoryFence(); // Update the read index SetNextReadLocation(InRingInfo, nextReadLocation); //DumpRingInfo(InRingInfo, "AFTER "); SpinlockRelease(InRingInfo->RingLock); return 0; }
/** Write data from buffer to serial device. Writes NumberOfBytes data bytes from Buffer to the serial device. The number of bytes actually written to the serial device is returned. If the return value is less than NumberOfBytes, then the write operation failed. If Buffer is NULL, then ASSERT(). If NumberOfBytes is zero, then return 0. @param Buffer Pointer to the data buffer to be written. @param NumberOfBytes Number of bytes to written to the serial device. @retval 0 NumberOfBytes is 0. @retval >0 The number of bytes written to the serial device. If this value is less than NumberOfBytes, then the write operation failed. **/ UINTN EFIAPI SerialPortWrite ( IN UINT8 *Buffer, IN UINTN NumberOfBytes ) { XENCONS_RING_IDX Consumer, Producer; UINTN Sent; ASSERT (Buffer != NULL); if (NumberOfBytes == 0) { return 0; } if (!mXenConsoleInterface) { return 0; } Sent = 0; do { Consumer = mXenConsoleInterface->out_cons; Producer = mXenConsoleInterface->out_prod; MemoryFence (); while (Sent < NumberOfBytes && ((Producer - Consumer) < sizeof (mXenConsoleInterface->out))) mXenConsoleInterface->out[MASK_XENCONS_IDX(Producer++, mXenConsoleInterface->out)] = Buffer[Sent++]; MemoryFence (); mXenConsoleInterface->out_prod = Producer; XenHypercallEventChannelOp (EVTCHNOP_send, &mXenConsoleEventChain); } while (Sent < NumberOfBytes); return Sent; }
EFI_STATUS EFIAPI PcatRootBridgeIoFlush ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This ) { // // Perform a fence operation to make sure all memory operations are flushed // MemoryFence(); return EFI_SUCCESS; }
/** Read data from serial device and save the datas in buffer. Reads NumberOfBytes data bytes from a serial device into the buffer specified by Buffer. The number of bytes actually read is returned. If Buffer is NULL, then ASSERT(). If NumberOfBytes is zero, then return 0. @param Buffer Pointer to the data buffer to store the data read from the serial device. @param NumberOfBytes Number of bytes which will be read. @retval 0 Read data failed, no data is to be read. @retval >0 Actual number of bytes read from serial device. **/ UINTN EFIAPI SerialPortRead ( OUT UINT8 *Buffer, IN UINTN NumberOfBytes ) { XENCONS_RING_IDX Consumer, Producer; UINTN Received; ASSERT (Buffer != NULL); if (NumberOfBytes == 0) { return 0; } if (!mXenConsoleInterface) { return 0; } Consumer = mXenConsoleInterface->in_cons; Producer = mXenConsoleInterface->in_prod; MemoryFence (); Received = 0; while (Received < NumberOfBytes && Consumer < Producer) Buffer[Received++] = mXenConsoleInterface->in[MASK_XENCONS_IDX(Consumer++, mXenConsoleInterface->in)]; MemoryFence (); mXenConsoleInterface->in_cons = Consumer; XenHypercallEventChannelOp (EVTCHNOP_send, &mXenConsoleEventChain); return Received; }
/*++ Name: RingBufferWrite() Description: Write to the ring buffer --*/ int RingBufferWrite( RING_BUFFER_INFO* OutRingInfo, SG_BUFFER_LIST SgBuffers[], UINT32 SgBufferCount ) { int i=0; UINT32 byteAvailToWrite; UINT32 byteAvailToRead; UINT32 totalBytesToWrite=0; volatile UINT32 nextWriteLocation; UINT64 prevIndices=0; DPRINT_ENTER(VMBUS); for (i=0; i < SgBufferCount; i++) { totalBytesToWrite += SgBuffers[i].Length; } totalBytesToWrite += sizeof(UINT64); SpinlockAcquire(OutRingInfo->RingLock); GetRingBufferAvailBytes(OutRingInfo, &byteAvailToRead, &byteAvailToWrite); DPRINT_DBG(VMBUS, "Writing %u bytes...", totalBytesToWrite); //DumpRingInfo(OutRingInfo, "BEFORE "); // If there is only room for the packet, assume it is full. Otherwise, the next time around, we think the ring buffer // is empty since the read index == write index if (byteAvailToWrite <= totalBytesToWrite) { DPRINT_DBG(VMBUS, "No more space left on outbound ring buffer (needed %u, avail %u)", totalBytesToWrite, byteAvailToWrite); SpinlockRelease(OutRingInfo->RingLock); DPRINT_EXIT(VMBUS); return -1; } // Write to the ring buffer nextWriteLocation = GetNextWriteLocation(OutRingInfo); for (i=0; i < SgBufferCount; i++) { nextWriteLocation = CopyToRingBuffer(OutRingInfo, nextWriteLocation, SgBuffers[i].Data, SgBuffers[i].Length); } // Set previous packet start prevIndices = GetRingBufferIndices(OutRingInfo); nextWriteLocation = CopyToRingBuffer(OutRingInfo, nextWriteLocation, &prevIndices, sizeof(UINT64)); // Make sure we flush all writes before updating the writeIndex MemoryFence(); // Now, update the write location SetNextWriteLocation(OutRingInfo, nextWriteLocation); //DumpRingInfo(OutRingInfo, "AFTER "); SpinlockRelease(OutRingInfo->RingLock); DPRINT_EXIT(VMBUS); return 0; }
EFI_STATUS EFIAPI PcatRootBridgeIoMap ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation, IN VOID *HostAddress, IN OUT UINTN *NumberOfBytes, OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, OUT VOID **Mapping ) { EFI_STATUS Status; EFI_PHYSICAL_ADDRESS PhysicalAddress; MAP_INFO *MapInfo; MAP_INFO_INSTANCE *MapInstance; PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; if ( HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL ) { return EFI_INVALID_PARAMETER; } // // Perform a fence operation to make sure all memory operations are flushed // MemoryFence(); // // Initialize the return values to their defaults // *Mapping = NULL; // // Make sure that Operation is valid // if ((UINT32)Operation >= EfiPciOperationMaximum) { return EFI_INVALID_PARAMETER; } // // Most PCAT like chipsets can not handle performing DMA above 4GB. // If any part of the DMA transfer being mapped is above 4GB, then // map the DMA transfer to a buffer below 4GB. // PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress; if ((PhysicalAddress + *NumberOfBytes) > 0x100000000ULL) { // // Common Buffer operations can not be remapped. If the common buffer // if above 4GB, then it is not possible to generate a mapping, so return // an error. // if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) { return EFI_UNSUPPORTED; } // // Allocate a MAP_INFO structure to remember the mapping when Unmap() is // called later. // Status = gBS->AllocatePool ( EfiBootServicesData, sizeof(MAP_INFO), (VOID **)&MapInfo ); if (EFI_ERROR (Status)) { *NumberOfBytes = 0; return Status; } // // Return a pointer to the MAP_INFO structure in Mapping // *Mapping = MapInfo; // // Initialize the MAP_INFO structure // MapInfo->Operation = Operation; MapInfo->NumberOfBytes = *NumberOfBytes; MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES(*NumberOfBytes); MapInfo->HostAddress = PhysicalAddress; MapInfo->MappedHostAddress = 0x00000000ffffffff; // // Allocate a buffer below 4GB to map the transfer to. // Status = gBS->AllocatePages ( AllocateMaxAddress, EfiBootServicesData, MapInfo->NumberOfPages, &MapInfo->MappedHostAddress ); if (EFI_ERROR(Status)) { gBS->FreePool (MapInfo); *NumberOfBytes = 0; return Status; } // // If this is a read operation from the Bus Master's point of view, // then copy the contents of the real buffer into the mapped buffer // so the Bus Master can read the contents of the real buffer. // if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) { CopyMem ( (VOID *)(UINTN)MapInfo->MappedHostAddress, (VOID *)(UINTN)MapInfo->HostAddress, MapInfo->NumberOfBytes ); } Status =gBS->AllocatePool ( EfiBootServicesData, sizeof(MAP_INFO_INSTANCE), (VOID **)&MapInstance ); if (EFI_ERROR(Status)) { gBS->FreePages (MapInfo->MappedHostAddress,MapInfo->NumberOfPages); gBS->FreePool (MapInfo); *NumberOfBytes = 0; return Status; } MapInstance->Map=MapInfo; PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); InsertTailList(&PrivateData->MapInfo,&MapInstance->Link); // // The DeviceAddress is the address of the maped buffer below 4GB // *DeviceAddress = MapInfo->MappedHostAddress; } else { // // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress // *DeviceAddress = PhysicalAddress; } // // Perform a fence operation to make sure all memory operations are flushed // MemoryFence(); return EFI_SUCCESS; }
EFI_STATUS EFIAPI PcatRootBridgeIoUnmap ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN VOID *Mapping ) { MAP_INFO *MapInfo; PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; LIST_ENTRY *Link; // // Perform a fence operation to make sure all memory operations are flushed // MemoryFence(); PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); // // See if the Map() operation associated with this Unmap() required a mapping buffer. // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS. // if (Mapping != NULL) { // // Get the MAP_INFO structure from Mapping // MapInfo = (MAP_INFO *)Mapping; for (Link = PrivateData->MapInfo.ForwardLink; Link != &PrivateData->MapInfo; Link = Link->ForwardLink) { if (((MAP_INFO_INSTANCE*)Link)->Map == MapInfo) break; } if (Link == &PrivateData->MapInfo) { return EFI_INVALID_PARAMETER; } RemoveEntryList(Link); ((MAP_INFO_INSTANCE*)Link)->Map = NULL; gBS->FreePool((MAP_INFO_INSTANCE*)Link); // // If this is a write operation from the Bus Master's point of view, // then copy the contents of the mapped buffer into the real buffer // so the processor can read the contents of the real buffer. // if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) { CopyMem ( (VOID *)(UINTN)MapInfo->HostAddress, (VOID *)(UINTN)MapInfo->MappedHostAddress, MapInfo->NumberOfBytes ); } // // Free the mapped buffer and the MAP_INFO structure. // gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages); gBS->FreePool (Mapping); } // // Perform a fence operation to make sure all memory operations are flushed // MemoryFence(); return EFI_SUCCESS; }
EFI_STATUS EFIAPI PcatRootBridgeIoMemRW ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, IN UINTN Count, IN BOOLEAN InStrideFlag, IN PTR In, IN BOOLEAN OutStrideFlag, OUT PTR Out ) /*++ Routine Description: Private service to provide the memory read/write Arguments: Width of the Memory Access Count of the number of accesses to perform Returns: Status EFI_SUCCESS - Successful transaction EFI_INVALID_PARAMETER - Unsupported width and address combination --*/ { UINTN Stride; UINTN InStride; UINTN OutStride; Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03); Stride = (UINTN)1 << Width; InStride = InStrideFlag ? Stride : 0; OutStride = OutStrideFlag ? Stride : 0; // // Loop for each iteration and move the data // switch (Width) { case EfiPciWidthUint8: for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) { MemoryFence(); *In.ui8 = *Out.ui8; MemoryFence(); } break; case EfiPciWidthUint16: for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) { MemoryFence(); *In.ui16 = *Out.ui16; MemoryFence(); } break; case EfiPciWidthUint32: for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) { MemoryFence(); *In.ui32 = *Out.ui32; MemoryFence(); } break; default: return EFI_INVALID_PARAMETER; } return EFI_SUCCESS; }
/* * UEFI Initialize() function * */ EFI_STATUS EFIAPI SnpInitialize ( IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp, IN UINTN RxBufferSize OPTIONAL, IN UINTN TxBufferSize OPTIONAL ) { EFI_STATUS Status; UINT32 PmConf; INT32 AllocResult; UINT32 RxStatusSize; UINT32 TxStatusSize; // Initialize variables // Global variables to hold tx and rx FIFO allocation gTxBuffer = 0; // Check Snp Instance if (Snp == NULL) { return EFI_INVALID_PARAMETER; } // First check that driver has not already been initialized if (Snp->Mode->State == EfiSimpleNetworkInitialized) { DEBUG ((EFI_D_WARN, "LAN9118 Driver already initialized\n")); return EFI_SUCCESS; } else if (Snp->Mode->State == EfiSimpleNetworkStopped) { DEBUG ((EFI_D_WARN, "LAN9118 Driver not started\n")); return EFI_NOT_STARTED; } // Initiate a PHY reset Status = PhySoftReset (PHY_RESET_PMT, Snp); if (EFI_ERROR (Status)) { Snp->Mode->State = EfiSimpleNetworkStopped; DEBUG ((EFI_D_WARN, "Warning: Link not ready after TimeOut. Check ethernet cable\n")); return EFI_NOT_STARTED; } // Initiate a software reset Status = SoftReset (0, Snp); if (EFI_ERROR(Status)) { DEBUG ((EFI_D_WARN, "Soft Reset Failed: Hardware Error\n")); return EFI_DEVICE_ERROR; } // Read the PM register PmConf = MmioRead32 (LAN9118_PMT_CTRL); // MPTCTRL_WOL_EN: Allow Wake-On-Lan to detect wake up frames or magic packets // MPTCTRL_ED_EN: Allow energy detection to allow lowest power consumption mode // MPTCTRL_PME_EN: Allow Power Management Events PmConf = 0; PmConf |= (MPTCTRL_WOL_EN | MPTCTRL_ED_EN | MPTCTRL_PME_EN); // Write the current configuration to the register MmioWrite32 (LAN9118_PMT_CTRL, PmConf); MemoryFence(); // Configure GPIO and HW Status = ConfigureHardware (HW_CONF_USE_LEDS, Snp); if (EFI_ERROR(Status)) { return Status; } // Assign the transmitter buffer size (default values) TxStatusSize = LAN9118_TX_STATUS_SIZE; RxStatusSize = LAN9118_RX_STATUS_SIZE; // Check that a buff size was specified if (TxBufferSize > 0) { if (RxBufferSize == 0) { RxBufferSize = LAN9118_RX_DATA_SIZE; } AllocResult = ChangeFifoAllocation ( ALLOC_USE_FIFOS, &TxBufferSize, &RxBufferSize, &TxStatusSize, &RxStatusSize, Snp ); if (AllocResult < 0) { return EFI_OUT_OF_RESOURCES; } } // Do auto-negotiation if supported Status = AutoNegotiate (AUTO_NEGOTIATE_ADVERTISE_ALL, Snp); if (EFI_ERROR(Status)) { DEBUG ((EFI_D_WARN, "LAN9118: Auto Negotiation failed.\n")); } // Configure flow control depending on speed capabilities Status = ConfigureFlow (0, 0, 0, 0, Snp); if (EFI_ERROR(Status)) { return Status; } // Enable the transmitter Status = StartTx (START_TX_MAC | START_TX_CFG, Snp); if (EFI_ERROR(Status)) { return Status; } // Now acknowledge all interrupts MmioWrite32 (LAN9118_INT_STS, ~0); // Declare the driver as initialized Snp->Mode->State = EfiSimpleNetworkInitialized; return Status; }
/* * UEFI Reset () function * */ EFI_STATUS EFIAPI SnpReset ( IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp, IN BOOLEAN Verification ) { UINT32 PmConf; UINT32 HwConf; UINT32 ResetFlags; EFI_STATUS Status; PmConf = 0; HwConf = 0; ResetFlags = 0; // Check Snp Instance if (Snp == NULL) { return EFI_INVALID_PARAMETER; } // First check that driver has not already been initialized if (Snp->Mode->State == EfiSimpleNetworkStarted) { DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not yet initialized\n")); return EFI_DEVICE_ERROR; } else if (Snp->Mode->State == EfiSimpleNetworkStopped) { DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not started\n")); return EFI_NOT_STARTED; } // Initiate a PHY reset Status = PhySoftReset (PHY_RESET_PMT, Snp); if (EFI_ERROR (Status)) { Snp->Mode->State = EfiSimpleNetworkStopped; return EFI_NOT_STARTED; } // Initiate a software reset ResetFlags |= SOFT_RESET_CHECK_MAC_ADDR_LOAD | SOFT_RESET_CLEAR_INT; if (Verification) { ResetFlags |= SOFT_RESET_SELF_TEST; } Status = SoftReset (ResetFlags, Snp); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_WARN, "Warning: Soft Reset Failed: Hardware Error\n")); return EFI_DEVICE_ERROR; } // Read the PM register PmConf = MmioRead32 (LAN9118_PMT_CTRL); // MPTCTRL_WOL_EN: Allow Wake-On-Lan to detect wake up frames or magic packets // MPTCTRL_ED_EN: Allow energy detection to allow lowest power consumption mode // MPTCTRL_PME_EN: Allow Power Management Events PmConf |= (MPTCTRL_WOL_EN | MPTCTRL_ED_EN | MPTCTRL_PME_EN); // Write the current configuration to the register MmioWrite32 (LAN9118_PMT_CTRL, PmConf); MemoryFence(); // Reactivate the LEDs Status = ConfigureHardware (HW_CONF_USE_LEDS, Snp); if (EFI_ERROR (Status)) { return Status; } // Check that a buffer size was specified in SnpInitialize if (gTxBuffer != 0) { HwConf = MmioRead32 (LAN9118_HW_CFG); // Read the HW register HwConf &= ~HW_CFG_TX_FIFO_SIZE_MASK; // Clear buffer bits first HwConf |= HW_CFG_TX_FIFO_SIZE(gTxBuffer); // assign size chosen in SnpInitialize MmioWrite32 (LAN9118_HW_CFG, HwConf); // Write the conf MemoryFence(); } // Enable the receiver and transmitter and clear their contents StartRx (START_RX_CLEAR, Snp); StartTx (START_TX_MAC | START_TX_CFG | START_TX_CLEAR, Snp); // Now acknowledge all interrupts MmioWrite32 (LAN9118_INT_STS, ~0); return EFI_SUCCESS; }