Beispiel #1
0
/**
  Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and
  writes the result back to the bit field in the 16-bit port.

  Reads the 16-bit PCI configuration register specified by Address, performs a
  bitwise OR between the read result and the value specified by
  OrData, and writes the result to the 16-bit PCI configuration register
  specified by Address. The value written to the PCI configuration register is
  returned. This function must guarantee that all PCI read and write operations
  are serialized. Extra left bits in OrData are stripped.

  If Address > 0x0FFFFFFF, then ASSERT().
  If Address is not aligned on a 16-bit boundary, then ASSERT().
  If StartBit is greater than 15, then ASSERT().
  If EndBit is greater than 15, then ASSERT().
  If EndBit is less than StartBit, then ASSERT().
  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().

  @param  Address   The PCI configuration register to write.
  @param  StartBit  The ordinal of the least significant bit in the bit field.
                    Range 0..15.
  @param  EndBit    The ordinal of the most significant bit in the bit field.
                    Range 0..15.
  @param  OrData    The value to OR with the PCI configuration register.

  @return The value written back to the PCI configuration register.

**/
UINT16
EFIAPI
PciBitFieldOr16 (
  IN      UINTN                     Address,
  IN      UINTN                     StartBit,
  IN      UINTN                     EndBit,
  IN      UINT16                    OrData
  )
{
  return PciWrite16 (
           Address,
           BitFieldOr16 (PciRead16 (Address), StartBit, EndBit, OrData)
           );
}
Beispiel #2
0
/**
  Writes a bit field to a PCI configuration register.

  Writes Value to the bit field of the PCI configuration register. The bit
  field is specified by the StartBit and the EndBit. All other bits in the
  destination PCI configuration register are preserved. The new value of the
  16-bit register is returned.

  If Address > 0x0FFFFFFF, then ASSERT().
  If Address is not aligned on a 16-bit boundary, then ASSERT().
  If StartBit is greater than 15, then ASSERT().
  If EndBit is greater than 15, then ASSERT().
  If EndBit is less than StartBit, then ASSERT().
  If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().

  @param  Address   The PCI configuration register to write.
  @param  StartBit  The ordinal of the least significant bit in the bit field.
                    Range 0..15.
  @param  EndBit    The ordinal of the most significant bit in the bit field.
                    Range 0..15.
  @param  Value     The new value of the bit field.

  @return The value written back to the PCI configuration register.

**/
UINT16
EFIAPI
PciBitFieldWrite16 (
  IN      UINTN                     Address,
  IN      UINTN                     StartBit,
  IN      UINTN                     EndBit,
  IN      UINT16                    Value
  )
{
  return PciWrite16 (
           Address,
           BitFieldWrite16 (PciRead16 (Address), StartBit, EndBit, Value)
           );
}
Beispiel #3
0
/** Perform USB erratas after MRC init.

**/
VOID
PlatformUsbErratasPostMrc (
  VOID
  )
{
  UINT32                            Index;
  UINT32                            TempBar0Addr;
  UINT16                            SaveCmdReg;
  UINT32                            SaveBar0Reg;

  TempBar0Addr = PcdGet32(PcdPeiQNCUsbControllerMemoryBaseAddress);

  //
  // Apply EHCI controller erratas.
  //
  for (Index = 0; Index < IOH_MAX_EHCI_USB_CONTROLLERS; Index++, TempBar0Addr += IOH_USB_CONTROLLER_MMIO_RANGE) {

    if ((PciRead16 (IohEhciPciReg[Index] + R_IOH_USB_VENDOR_ID)) != V_IOH_USB_VENDOR_ID) {
      continue;  // Device not enabled, skip.
    }

    //
    // Save current settings for PCI CMD/BAR0 registers
    //
    SaveCmdReg = PciRead16 (IohEhciPciReg[Index] + R_IOH_USB_COMMAND);
    SaveBar0Reg = PciRead32 (IohEhciPciReg[Index] + R_IOH_USB_MEMBAR);

    //
    // Temp. assign base address register, Enable Memory Space.
    //
    PciWrite32 ((IohEhciPciReg[Index] + R_IOH_USB_MEMBAR), TempBar0Addr);
    PciWrite16 (IohEhciPciReg[Index] + R_IOH_USB_COMMAND, SaveCmdReg | B_IOH_USB_COMMAND_MSE);


    //
    // Set packet buffer OUT/IN thresholds.
    //
    MmioAndThenOr32 (
      TempBar0Addr + R_IOH_EHCI_INSNREG01,
      (UINT32) (~(B_IOH_EHCI_INSNREG01_OUT_THRESHOLD_MASK | B_IOH_EHCI_INSNREG01_IN_THRESHOLD_MASK)),
      (UINT32) ((EHCI_OUT_THRESHOLD_VALUE << B_IOH_EHCI_INSNREG01_OUT_THRESHOLD_BP) | (EHCI_IN_THRESHOLD_VALUE << B_IOH_EHCI_INSNREG01_IN_THRESHOLD_BP))
      );

    //
    // Restore settings for PCI CMD/BAR0 registers
    //
    PciWrite32 ((IohEhciPciReg[Index] + R_IOH_USB_MEMBAR), SaveBar0Reg);
    PciWrite16 (IohEhciPciReg[Index] + R_IOH_USB_COMMAND, SaveCmdReg);
  }

  //
  // Apply USB device controller erratas.
  //
  for (Index = 0; Index < IOH_MAX_USBDEVICE_USB_CONTROLLERS; Index++, TempBar0Addr += IOH_USB_CONTROLLER_MMIO_RANGE) {

    if ((PciRead16 (IohUsbDevicePciReg[Index] + R_IOH_USB_VENDOR_ID)) != V_IOH_USB_VENDOR_ID) {
      continue;  // Device not enabled, skip.
    }

    //
    // Save current settings for PCI CMD/BAR0 registers
    //
    SaveCmdReg = PciRead16 (IohUsbDevicePciReg[Index] + R_IOH_USB_COMMAND);
    SaveBar0Reg = PciRead32 (IohUsbDevicePciReg[Index] + R_IOH_USB_MEMBAR);

    //
    // Temp. assign base address register, Enable Memory Space.
    //
    PciWrite32 ((IohUsbDevicePciReg[Index] + R_IOH_USB_MEMBAR), TempBar0Addr);
    PciWrite16 (IohUsbDevicePciReg[Index] + R_IOH_USB_COMMAND, SaveCmdReg | B_IOH_USB_COMMAND_MSE);

    //
    // Erratas for USB Device interrupt registers.
    //

    //
    // 1st Mask interrupts.
    //
    MmioWrite32 (
      TempBar0Addr + R_IOH_USBDEVICE_D_INTR_MSK_UDC_REG,
      V_IOH_USBDEVICE_D_INTR_MSK_UDC_REG
      );
    //
    // 2nd RW/1C of equivalent status bits.
    //
    MmioWrite32 (
      TempBar0Addr + R_IOH_USBDEVICE_D_INTR_UDC_REG,
      V_IOH_USBDEVICE_D_INTR_MSK_UDC_REG
      );

    //
    // 1st Mask end point interrupts.
    //
    MmioWrite32 (
      TempBar0Addr + R_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG,
      V_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG
      );
    //
    // 2nd RW/1C of equivalent end point status bits.
    //
    MmioWrite32 (
      TempBar0Addr + R_IOH_USBDEVICE_EP_INTR_UDC_REG,
      V_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG
      );

    //
    // Restore settings for PCI CMD/BAR0 registers
    //
    PciWrite32 ((IohUsbDevicePciReg[Index] + R_IOH_USB_MEMBAR), SaveBar0Reg);
    PciWrite16 (IohUsbDevicePciReg[Index] + R_IOH_USB_COMMAND, SaveCmdReg);
  }
}
Beispiel #4
0
/* For each function we create a 
 * pci_device and add it to the list */
void PciCheckFunction(list_t *Bridge, uint8_t Bus, uint8_t Device, uint8_t Function)
{
	uint8_t SecondBus;
	PciNativeHeader_t *Pcs;
	PciDevice_t *PciDevice;

	/* Allocate */
	Pcs = (PciNativeHeader_t*)kmalloc(sizeof(PciNativeHeader_t));
	PciDevice = (PciDevice_t*)kmalloc(sizeof(PciDevice_t));

	/* Get full information */
	PciReadFunction(Pcs, Bus, Device, Function);

	/* Set information */
	PciDevice->Header = Pcs;
	PciDevice->Bus = Bus;
	PciDevice->Device = Device;
	PciDevice->Function = Function;
	PciDevice->Children = NULL;

	/* Info 
	 * Ignore the spam of device_id 0x7a0 in VMWare*/
	if (Pcs->DeviceId != 0x7a0)
	{
#ifdef X86_PCI_DIAGNOSE
		printf("    * [%d:%d:%d][%d:%d:%d] Vendor 0x%x, Device 0x%x : %s\n",
			Pcs->Class, Pcs->Subclass, Pcs->Interface,
			Bus, Device, Function,
			Pcs->VendorId, Pcs->DeviceId,
			PciToString(Pcs->Class, Pcs->Subclass, Pcs->Interface));
#endif
	}

	/* Do some disabling, but NOT on the video or bridge */
	if ((Pcs->Class != PCI_DEVICE_CLASS_BRIDGE) && (Pcs->Class != PCI_DEVICE_CLASS_VIDEO))
	{
		/* Disable Device untill further notice */
		uint16_t PciSettings = PciRead16(Bus, Device, Function, 0x04);
		PciWrite16(Bus, Device, Function, 0x04, PciSettings | X86_PCI_COMMAND_INTDISABLE);
	}
	
	/* Add to list */
	if (Pcs->Class == PCI_DEVICE_CLASS_BRIDGE && Pcs->Subclass == PCI_DEVICE_SUBCLASS_PCI)
	{
		PciDevice->Type = X86_PCI_TYPE_BRIDGE;
		list_append(Bridge, list_create_node(X86_PCI_TYPE_BRIDGE, PciDevice));
	}
	else
	{
		PciDevice->Type = X86_PCI_TYPE_DEVICE;
		list_append(Bridge, list_create_node(X86_PCI_TYPE_DEVICE, PciDevice));
	}

	/* Is this a secondary (PCI) bus */
	if ((Pcs->Class == PCI_DEVICE_CLASS_BRIDGE) && (Pcs->Subclass == PCI_DEVICE_SUBCLASS_PCI))
	{
		/* Uh oh, this dude has children */
		PciDevice->Children = list_create(LIST_SAFE);

		SecondBus = PciReadSecondaryBusNumber(Bus, Device, Function);
		PciCheckBus(PciDevice->Children, SecondBus);
	}
}
Beispiel #5
0
/**
  Copies the data in a caller supplied buffer to a specified range of PCI
  configuration space.

  Writes the range of PCI configuration registers specified by StartAddress and
  Size from the buffer specified by Buffer. This function only allows the PCI
  configuration registers from a single PCI function to be written. Size is
  returned. When possible 32-bit PCI configuration write cycles are used to
  write from StartAdress to StartAddress + Size. Due to alignment restrictions,
  8-bit and 16-bit PCI configuration write cycles may be used at the beginning
  and the end of the range.

  If StartAddress > 0x0FFFFFFF, then ASSERT().
  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
  If Size > 0 and Buffer is NULL, then ASSERT().

  @param  StartAddress  The starting address that encodes the PCI Bus, Device,
                        Function and Register.
  @param  Size          The size in bytes of the transfer.
  @param  Buffer        The pointer to a buffer containing the data to write.

  @return Size written to StartAddress.

**/
UINTN
EFIAPI
PciWriteBuffer (
  IN      UINTN                     StartAddress,
  IN      UINTN                     Size,
  IN      VOID                      *Buffer
  )
{
  UINTN                             ReturnValue;

  ASSERT_INVALID_PCI_ADDRESS (StartAddress, 0);
  ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);

  if (Size == 0) {
    return 0;
  }

  ASSERT (Buffer != NULL);

  //
  // Save Size for return
  //
  ReturnValue = Size;

  if ((StartAddress & BIT0) != 0) {
    //
    // Write a byte if StartAddress is byte aligned
    //
    PciWrite8 (StartAddress, *(UINT8*)Buffer);
    StartAddress += sizeof (UINT8);
    Size -= sizeof (UINT8);
    Buffer = (UINT8*)Buffer + 1;
  }

  if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) {
    //
    // Write a word if StartAddress is word aligned
    //
    PciWrite16 (StartAddress, ReadUnaligned16 (Buffer));
    StartAddress += sizeof (UINT16);
    Size -= sizeof (UINT16);
    Buffer = (UINT16*)Buffer + 1;
  }

  while (Size >= sizeof (UINT32)) {
    //
    // Write as many double words as possible
    //
    PciWrite32 (StartAddress, ReadUnaligned32 (Buffer));
    StartAddress += sizeof (UINT32);
    Size -= sizeof (UINT32);
    Buffer = (UINT32*)Buffer + 1;
  }

  if (Size >= sizeof (UINT16)) {
    //
    // Write the last remaining word if exist
    //
    PciWrite16 (StartAddress, ReadUnaligned16 (Buffer));
    StartAddress += sizeof (UINT16);
    Size -= sizeof (UINT16);
    Buffer = (UINT16*)Buffer + 1;
  }

  if (Size >= sizeof (UINT8)) {
    //
    // Write the last remaining byte if exist
    //
    PciWrite8 (StartAddress, *(UINT8*)Buffer);
  }

  return ReturnValue;
}
/**
  Performs any early platform specific GPIO Controller manipulation.

**/
VOID
EFIAPI
EarlyPlatformGpioCtrlerManipulation (
  VOID
  )
{
  UINT32                            IohGpioBase;
  UINT32                            Data32;
  UINT32                            Addr;
  UINT32                            DevPcieAddr;
  UINT16                            SaveCmdReg;
  UINT32                            SaveBarReg;
  UINT16                            PciVid;
  UINT16                            PciDid;

  IohGpioBase = (UINT32) PcdGet64 (PcdIohGpioMmioBase);

  DevPcieAddr = PCI_LIB_ADDRESS (
                  PcdGet8 (PcdIohGpioBusNumber),
                  PcdGet8 (PcdIohGpioDevNumber),
                  PcdGet8 (PcdIohGpioFunctionNumber),
                  0
                  );

  //
  // Do nothing if not a supported device.
  //
  PciVid = PciRead16 (DevPcieAddr + PCI_VENDOR_ID_OFFSET);
  PciDid = PciRead16 (DevPcieAddr + PCI_DEVICE_ID_OFFSET);
  if((PciVid != V_IOH_I2C_GPIO_VENDOR_ID) || (PciDid != V_IOH_I2C_GPIO_DEVICE_ID)) {
    return;
  }

  //
  // Save current settings for PCI CMD/BAR registers.
  //
  SaveCmdReg = PciRead16 (DevPcieAddr + PCI_COMMAND_OFFSET);
  SaveBarReg = PciRead32 (DevPcieAddr + PcdGet8 (PcdIohGpioBarRegister));

  //
  // Use predefined tempory memory resource.
  //
  PciWrite32 ( DevPcieAddr + PcdGet8 (PcdIohGpioBarRegister), IohGpioBase);
  PciWrite8 ( DevPcieAddr + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);

  //
  // Gpio Controller Manipulation Tasks.
  //

    //
    // Reset Cypress Expander on Galileo Platform
    //
    Addr = IohGpioBase + GPIO_SWPORTA_DR;
    Data32 = *((volatile UINT32 *) (UINTN)(Addr));
    Data32 |= BIT4;                                 // Cypress Reset line controlled by GPIO<4>
    *((volatile UINT32 *) (UINTN)(Addr)) = Data32;

    Data32 = *((volatile UINT32 *) (UINTN)(Addr));
    Data32 &= ~BIT4;                                // Cypress Reset line controlled by GPIO<4>
    *((volatile UINT32 *) (UINTN)(Addr)) = Data32;

  //
  // Restore settings for PCI CMD/BAR registers
  //
  PciWrite32 ((DevPcieAddr + PcdGet8 (PcdIohGpioBarRegister)), SaveBarReg);
  PciWrite16 (DevPcieAddr + PCI_COMMAND_OFFSET, SaveCmdReg);
}
Beispiel #7
0
/* For each function we create a 
 * pci_device and add it to the list */
void PciCheckFunction(list_t *Bridge, PciBus_t *BusIo, uint8_t Bus, uint8_t Device, uint8_t Function)
{
	/* Vars */
	MCoreDevice_t *mDevice;
	uint8_t SecondBus;
	PciNativeHeader_t *Pcs;
	PciDevice_t *PciDevice;

	/* Allocate */
	Pcs = (PciNativeHeader_t*)kmalloc(sizeof(PciNativeHeader_t));
	PciDevice = (PciDevice_t*)kmalloc(sizeof(PciDevice_t));

	/* Get full information */
	PciReadFunction(Pcs, BusIo, Bus, Device, Function);

	/* Set information */
	PciDevice->PciBus = BusIo;
	PciDevice->Header = Pcs;
	PciDevice->Bus = Bus;
	PciDevice->Device = Device;
	PciDevice->Function = Function;
	PciDevice->Children = NULL;

	/* Info 
	 * Ignore the spam of device_id 0x7a0 in VMWare*/
	if (Pcs->DeviceId != 0x7a0)
	{
#ifdef X86_PCI_DIAGNOSE
		printf("    * [%d:%d:%d][%d:%d:%d] Vendor 0x%x, Device 0x%x : %s\n",
			Pcs->Class, Pcs->Subclass, Pcs->Interface,
			Bus, Device, Function,
			Pcs->VendorId, Pcs->DeviceId,
			PciToString(Pcs->Class, Pcs->Subclass, Pcs->Interface));
#endif
	}

	/* Do some disabling, but NOT on the video or bridge */
	if ((Pcs->Class != PCI_DEVICE_CLASS_BRIDGE) 
		&& (Pcs->Class != PCI_DEVICE_CLASS_VIDEO))
	{
		/* Disable Device untill further notice */
		uint16_t PciSettings = PciRead16(BusIo, Bus, Device, Function, 0x04);
		PciWrite16(BusIo, Bus, Device, Function, 0x04, PciSettings | X86_PCI_COMMAND_INTDISABLE);
	}
	
	/* Add to list */
	if (Pcs->Class == PCI_DEVICE_CLASS_BRIDGE && Pcs->Subclass == PCI_DEVICE_SUBCLASS_PCI)
	{
		PciDevice->Type = X86_PCI_TYPE_BRIDGE;
		list_append(Bridge, list_create_node(X86_PCI_TYPE_BRIDGE, PciDevice));

		/* Uh oh, this dude has children */
		PciDevice->Children = list_create(LIST_SAFE);

		/* Get secondary bus no and iterate */
		SecondBus = PciReadSecondaryBusNumber(BusIo, Bus, Device, Function);
		PciCheckBus(PciDevice->Children, BusIo, SecondBus);
	}
	else
	{
		/* This is an device */
		PciDevice->Type = X86_PCI_TYPE_DEVICE;
		list_append(Bridge, list_create_node(X86_PCI_TYPE_DEVICE, PciDevice));

		/* Register device with the OS */
		mDevice = (MCoreDevice_t*)kmalloc(sizeof(MCoreDevice_t));
		memset(mDevice, 0, sizeof(MCoreDevice_t));
		
		/* Setup information */
		mDevice->VendorId = Pcs->VendorId;
		mDevice->DeviceId = Pcs->DeviceId;
		mDevice->Class = Pcs->Class;
		mDevice->Subclass = Pcs->Subclass;
		mDevice->Interface = Pcs->Interface;

		mDevice->Segment = (DevInfo_t)BusIo->Segment;
		mDevice->Bus = Bus;
		mDevice->Device = Device;
		mDevice->Function = Function;

		mDevice->IrqLine = -1;
		mDevice->IrqPin = (int)Pcs->InterruptPin;
		mDevice->IrqAvailable[0] = Pcs->InterruptLine;

		/* Type */
		mDevice->Type = DeviceUnknown;
		mDevice->Data = NULL;

		/* Save bus information */
		mDevice->BusInformation = PciDevice;

		/* Initial */
		mDevice->Driver.Name = NULL;
		mDevice->Driver.Version = -1;
		mDevice->Driver.Data = NULL;
		mDevice->Driver.Status = DriverNone;

		/* Read Bars */
		PciReadBars(BusIo, mDevice, Pcs->HeaderType);

		/* Register */
		DmCreateDevice((char*)PciToString(Pcs->Class, Pcs->Subclass, Pcs->Interface), mDevice);
	}
}