Ejemplo n.º 1
0
Archivo: pci.c Proyecto: google/rekall
static NTSTATUS DumpBaseAddressRegister64(u8 bus, u8 slot, u8 func, u8 offset,
					  struct PmemMemoryInfo *info, int len) {
  u64 base = read_pci_config(bus, slot, func, offset);
  u32 base_high = read_pci_config(bus, slot, func, offset + sizeof(u32));
  u32 mask = 0;
  u32 mask_high = 0;
  u64 end = 0;
  u16 command = read_pci_config_16(bus, slot, func, PCI_COMMAND);

  // Disable IO and memory bus access.
  write_pci_config_16(bus, slot, func, PCI_COMMAND, 0);

  // Check the lower word first.
  write_pci_config(bus, slot, func, offset, 0xFFFFFFFF);
  mask = read_pci_config(bus, slot, func, offset) & 0xFFFFFFF0;
  write_pci_config(bus, slot, func, offset, (u32)base);

  // Check the upper 32 bit word.
  write_pci_config(bus, slot, func, offset + sizeof(u32), 0xFFFFFFFF);
  mask_high = read_pci_config(bus, slot, func, offset + sizeof(u32));
  write_pci_config(bus, slot, func, offset + sizeof(u32), (u32)base_high);

  // Reenable bus access.
  write_pci_config_16(bus, slot, func, PCI_COMMAND, command);

  base = ((base & 0xFFFFFFF0) | ((u64)base_high) << 32);
  end = ~(mask | ((u64)mask_high) << 32) + base;

  return InsertMemoryHole(info, len, base, end);
};
Ejemplo n.º 2
0
static void __iomem * __init xdbc_map_pci_mmio(u32 bus, u32 dev, u32 func)
{
	u64 val64, sz64, mask64;
	void __iomem *base;
	u32 val, sz;
	u8 byte;

	val = read_pci_config(bus, dev, func, PCI_BASE_ADDRESS_0);
	write_pci_config(bus, dev, func, PCI_BASE_ADDRESS_0, ~0);
	sz = read_pci_config(bus, dev, func, PCI_BASE_ADDRESS_0);
	write_pci_config(bus, dev, func, PCI_BASE_ADDRESS_0, val);

	if (val == 0xffffffff || sz == 0xffffffff) {
		pr_notice("invalid mmio bar\n");
		return NULL;
	}

	val64	= val & PCI_BASE_ADDRESS_MEM_MASK;
	sz64	= sz & PCI_BASE_ADDRESS_MEM_MASK;
	mask64	= PCI_BASE_ADDRESS_MEM_MASK;

	if ((val & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) {
		val = read_pci_config(bus, dev, func, PCI_BASE_ADDRESS_0 + 4);
		write_pci_config(bus, dev, func, PCI_BASE_ADDRESS_0 + 4, ~0);
		sz = read_pci_config(bus, dev, func, PCI_BASE_ADDRESS_0 + 4);
		write_pci_config(bus, dev, func, PCI_BASE_ADDRESS_0 + 4, val);

		val64	|= (u64)val << 32;
		sz64	|= (u64)sz << 32;
		mask64	|= ~0ULL << 32;
	}

	sz64 &= mask64;

	if (!sz64) {
		pr_notice("invalid mmio address\n");
		return NULL;
	}

	sz64 = 1ULL << __ffs64(sz64);

	/* Check if the mem space is enabled: */
	byte = read_pci_config_byte(bus, dev, func, PCI_COMMAND);
	if (!(byte & PCI_COMMAND_MEMORY)) {
		byte |= PCI_COMMAND_MEMORY;
		write_pci_config_byte(bus, dev, func, PCI_COMMAND, byte);
	}

	xdbc.xhci_start = val64;
	xdbc.xhci_length = sz64;
	base = early_ioremap(val64, sz64);

	return base;
}
int __init get_iommu_capabilities(u8 bus, u8 dev, u8 func, u8 cap_ptr,
            struct amd_iommu *iommu)
{
    u32 cap_header, cap_range;
    u64 mmio_bar;

    /* remove it when BIOS available */
    write_pci_config(bus, dev, func,
        cap_ptr + PCI_CAP_MMIO_BAR_HIGH_OFFSET, 0x00000000);
    write_pci_config(bus, dev, func,
        cap_ptr + PCI_CAP_MMIO_BAR_LOW_OFFSET, 0x40000001);
    /* remove it when BIOS available */

    mmio_bar = (u64)read_pci_config(bus, dev, func,
             cap_ptr + PCI_CAP_MMIO_BAR_HIGH_OFFSET) << 32;
    mmio_bar |= read_pci_config(bus, dev, func,
            cap_ptr + PCI_CAP_MMIO_BAR_LOW_OFFSET) &
            PCI_CAP_MMIO_BAR_LOW_MASK;
    iommu->mmio_base_phys = (unsigned long)mmio_bar;

    if ( (mmio_bar == 0) || ( (mmio_bar & 0x3FFF) != 0 ) ) {
        dprintk(XENLOG_ERR ,
                "AMD IOMMU: Invalid MMIO_BAR = 0x%"PRIx64"\n", mmio_bar);
        return -ENODEV;
    }

    cap_header = read_pci_config(bus, dev, func, cap_ptr);
    iommu->revision = get_field_from_reg_u32(cap_header,
                  PCI_CAP_REV_MASK, PCI_CAP_REV_SHIFT);
    iommu->iotlb_support = get_field_from_reg_u32(cap_header,
                PCI_CAP_IOTLB_MASK, PCI_CAP_IOTLB_SHIFT);
    iommu->ht_tunnel_support = get_field_from_reg_u32(cap_header,
                    PCI_CAP_HT_TUNNEL_MASK,
                    PCI_CAP_HT_TUNNEL_SHIFT);
    iommu->not_present_cached = get_field_from_reg_u32(cap_header,
                    PCI_CAP_NP_CACHE_MASK,
                    PCI_CAP_NP_CACHE_SHIFT);

    cap_range = read_pci_config(bus, dev, func,
            cap_ptr + PCI_CAP_RANGE_OFFSET);
    iommu->root_bus = get_field_from_reg_u32(cap_range,
                PCI_CAP_BUS_NUMBER_MASK,
                PCI_CAP_BUS_NUMBER_SHIFT);
    iommu->first_devfn = get_field_from_reg_u32(cap_range,
                PCI_CAP_FIRST_DEVICE_MASK,
                PCI_CAP_FIRST_DEVICE_SHIFT);
    iommu->last_devfn = get_field_from_reg_u32(cap_range,
                PCI_CAP_LAST_DEVICE_MASK,
                PCI_CAP_LAST_DEVICE_SHIFT);

    return 0;
}
Ejemplo n.º 4
0
static void __init fix_hypertransport_config(int num, int slot, int func)
{
	u32 htcfg;
	/*
	 * we found a hypertransport bus
	 * make sure that we are broadcasting
	 * interrupts to all cpus on the ht bus
	 * if we're using extended apic ids
	 */
	htcfg = read_pci_config(num, slot, func, 0x68);
	if (htcfg & (1 << 18)) {
		printk(KERN_INFO "Detected use of extended apic ids "
				 "on hypertransport bus\n");
		if ((htcfg & (1 << 17)) == 0) {
			printk(KERN_INFO "Enabling hypertransport extended "
					 "apic interrupt broadcast\n");
			printk(KERN_INFO "Note this is a bios bug, "
					 "please contact your hw vendor\n");
			htcfg |= (1 << 17);
			write_pci_config(num, slot, func, 0x68, htcfg);
		}
	}


}
Ejemplo n.º 5
0
Archivo: pci.c Proyecto: google/rekall
static NTSTATUS DumpBaseAddressRegister32(u8 bus, u8 slot, u8 func, u8 offset,
					  struct PmemMemoryInfo *info, int len) {
  u32 mask = 0;
  u32 base = read_pci_config(bus, slot, func, offset);
  u16 command = read_pci_config_16(bus, slot, func, PCI_COMMAND);

  // Disable IO and memory bus access.
  write_pci_config_16(bus, slot, func, PCI_COMMAND, 0);

  write_pci_config(bus, slot, func, offset, 0xFFFFFFFF);
  mask = read_pci_config(bus, slot, func, offset) & 0xFFFFFFF0;
  write_pci_config(bus, slot, func, offset, base);

  // Reenable bus access.
  write_pci_config_16(bus, slot, func, PCI_COMMAND, command);

  base = base & 0xFFFFFFF0;
  return InsertMemoryHole(info, len, base, ~mask + base);
};
Ejemplo n.º 6
0
ACPI_STATUS
AcpiOsWritePciConfiguration (
    ACPI_PCI_ID             *PciId,
    UINT32                  PciRegister,
    UINT64                  Value,
    UINT32                  Width)
{
	write_pci_config(PciId->Segment, PciId->Bus,
				PciId->Device, PciId->Function,
				PciRegister, Value);
	return (AE_OK);
}
Ejemplo n.º 7
0
Archivo: pci.c Proyecto: google/rekall
u32 get_base_register_size(u8 bus, u8 slot, u8 func, u8 offset) {
  __int32 base = read_pci_config(bus, slot, func, offset);
  u32 mask = 0;
  u16 command =0;

  if (base == 0) return 0;

  command = read_pci_config_16(bus, slot, func, PCI_COMMAND);

  // Disable IO and memory bus access.
  write_pci_config_16(bus, slot, func, PCI_COMMAND, 0);

  // Write to config space all 0xFFFFFFFF
  write_pci_config(bus, slot, func, offset, 0xFFFFFFFF);
  mask = read_pci_config(bus, slot, func, offset) & 0xFFFFFFF0;
  write_pci_config(bus, slot, func, offset, base);

  // Reenable bus access.
  write_pci_config_16(bus, slot, func, PCI_COMMAND, command);

  return ~mask + base;
};
Ejemplo n.º 8
0
static u32 __init ati_ixp4x0_rev(int num, int slot, int func)
{
	u32 d;
	u8  b;

	b = read_pci_config_byte(num, slot, func, 0xac);
	b &= ~(1<<5);
	write_pci_config_byte(num, slot, func, 0xac, b);

	d = read_pci_config(num, slot, func, 0x70);
	d |= 1<<8;
	write_pci_config(num, slot, func, 0x70, d);

	d = read_pci_config(num, slot, func, 0x8);
	d &= 0xff;
	return d;
}
Ejemplo n.º 9
0
/* config_addr size value -- status */
static int
rc_write_pcicfg( ulong args[], ulong ret[] ) 
{
	pci_addr_t addr;

	/* printm("RTAS: write_pci_config (%ld:%02lX) + 0x%02lx %08lX [%ld]\n", 
		   (args[0]>>16)&0xff, (args[0]>>8)&0xff, args[0]&0xff, args[2], args[1] ); */
	if( args[1] == 2 )
		args[2] = ld_le32( &args[2] ) >> 16;
	if( args[1] == 4 )
		args[2] = ld_le32( &args[2] );

	/* XXX: don't know how to handle different PCI domains... */

	addr = PCIADDR_FROM_BUS_DEVFN( 0, (args[0]>>16)&0xff, (args[0]>>8)&0xff );
	write_pci_config( addr, args[0]&0xff, args[2], args[1] );
	ret[0] = 0;
	return 0;
}