Пример #1
0
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);
  }
}
Пример #2
0
/**

  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;
}
Пример #3
0
/**

  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;
}
Пример #4
0
/**
  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;
}
Пример #5
0
/**
  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;
}
Пример #6
0
/**
  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;
}
Пример #7
0
/**
  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;
}
Пример #8
0
/**
  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;
}
Пример #9
0
/**
  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;
}
Пример #10
0
/**
  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;
}
Пример #11
0
/**
  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;
}
Пример #12
0
/**
  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);
  }
}
Пример #13
0
/**
  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;
}
Пример #14
0
/**
  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;
}
Пример #15
0
/**
  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;
}
Пример #16
0
/**
  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;
}
Пример #18
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;
}
Пример #19
0
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;
}
Пример #20
0
/**
  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;
}
Пример #22
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;
}
Пример #23
0
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;
}
Пример #24
0
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;
}
Пример #25
0
/*
 *  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;
}
Пример #26
0
/*
 *  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;
}