Ejemplo n.º 1
0
/*
 * QUIRK to workaround cantiga VT-d buffer flush issue.
 * The workaround is to force write buffer flush even if
 * VT-d capability indicates it is not required.
 */
static void cantiga_b3_errata_init(void)
{
    u16 vid;
    u8 did_hi, rid;

    vid = pci_conf_read16(0, IGD_DEV, 0, 0);
    if ( vid != 0x8086 )
        return;

    did_hi = pci_conf_read8(0, IGD_DEV, 0, 3);
    rid = pci_conf_read8(0, IGD_DEV, 0, 8);

    if ( (did_hi == 0x2A) && (rid == 0x7) )
        is_cantiga_b3 = 1;
}
Ejemplo n.º 2
0
Archivo: pci.c Proyecto: chao-p/xen
static void check_pdev(const struct pci_dev *pdev)
{
#define PCI_STATUS_CHECK \
    (PCI_STATUS_PARITY | PCI_STATUS_SIG_TARGET_ABORT | \
     PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_REC_MASTER_ABORT | \
     PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY)
    u16 seg = pdev->seg;
    u8 bus = pdev->bus;
    u8 dev = PCI_SLOT(pdev->devfn);
    u8 func = PCI_FUNC(pdev->devfn);
    u16 val;

    if ( command_mask )
    {
        val = pci_conf_read16(seg, bus, dev, func, PCI_COMMAND);
        if ( val & command_mask )
            pci_conf_write16(seg, bus, dev, func, PCI_COMMAND,
                             val & ~command_mask);
        val = pci_conf_read16(seg, bus, dev, func, PCI_STATUS);
        if ( val & PCI_STATUS_CHECK )
        {
            printk(XENLOG_INFO "%04x:%02x:%02x.%u status %04x -> %04x\n",
                   seg, bus, dev, func, val, val & ~PCI_STATUS_CHECK);
            pci_conf_write16(seg, bus, dev, func, PCI_STATUS,
                             val & PCI_STATUS_CHECK);
        }
    }

    switch ( pci_conf_read8(seg, bus, dev, func, PCI_HEADER_TYPE) & 0x7f )
    {
    case PCI_HEADER_TYPE_BRIDGE:
        if ( !bridge_ctl_mask )
            break;
        val = pci_conf_read16(seg, bus, dev, func, PCI_BRIDGE_CONTROL);
        if ( val & bridge_ctl_mask )
            pci_conf_write16(seg, bus, dev, func, PCI_BRIDGE_CONTROL,
                             val & ~bridge_ctl_mask);
        val = pci_conf_read16(seg, bus, dev, func, PCI_SEC_STATUS);
        if ( val & PCI_STATUS_CHECK )
        {
            printk(XENLOG_INFO
                   "%04x:%02x:%02x.%u secondary status %04x -> %04x\n",
                   seg, bus, dev, func, val, val & ~PCI_STATUS_CHECK);
            pci_conf_write16(seg, bus, dev, func, PCI_SEC_STATUS,
                             val & PCI_STATUS_CHECK);
        }
        break;

    case PCI_HEADER_TYPE_CARDBUS:
        /* TODO */
        break;
    }
#undef PCI_STATUS_CHECK
}
Ejemplo n.º 3
0
/* 5500/5520/X58 Chipset Interrupt remapping errata, for stepping B-3.
 * Fixed in stepping C-2. */
static void __init tylersburg_intremap_quirk(void)
{
    uint32_t bus, device;
    uint8_t rev;

    for ( bus = 0; bus < 0x100; bus++ )
    {
        /* Match on System Management Registers on Device 20 Function 0 */
        device = pci_conf_read32(bus, 20, 0, PCI_VENDOR_ID);
        rev = pci_conf_read8(bus, 20, 0, PCI_REVISION_ID);

        if ( rev == 0x13 && device == 0x342e8086 )
        {
            printk(XENLOG_WARNING VTDPREFIX
                   "Disabling IOMMU due to Intel 5500/5520/X58 Chipset errata #47, #53\n");
            iommu_enabled = 0;
            break;
        }
    }
}
Ejemplo n.º 4
0
static struct pci_dev *alloc_pdev(struct pci_seg *pseg, u8 bus, u8 devfn)
{
    struct pci_dev *pdev;

    list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
        if ( pdev->bus == bus && pdev->devfn == devfn )
            return pdev;

    pdev = xzalloc(struct pci_dev);
    if ( !pdev )
        return NULL;

    *(u16*) &pdev->seg = pseg->nr;
    *((u8*) &pdev->bus) = bus;
    *((u8*) &pdev->devfn) = devfn;
    pdev->domain = NULL;
    INIT_LIST_HEAD(&pdev->msi_list);

    if ( pci_find_cap_offset(pseg->nr, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
                             PCI_CAP_ID_MSIX) )
    {
        struct arch_msix *msix = xzalloc(struct arch_msix);

        if ( !msix )
        {
            xfree(pdev);
            return NULL;
        }
        spin_lock_init(&msix->table_lock);
        pdev->msix = msix;
    }

    list_add(&pdev->alldevs_list, &pseg->alldevs_list);

    /* update bus2bridge */
    switch ( pdev->type = pdev_type(pseg->nr, bus, devfn) )
    {
        int pos;
        u16 cap;
        u8 sec_bus, sub_bus;

        case DEV_TYPE_PCIe2PCI_BRIDGE:
        case DEV_TYPE_LEGACY_PCI_BRIDGE:
            sec_bus = pci_conf_read8(pseg->nr, bus, PCI_SLOT(devfn),
                                     PCI_FUNC(devfn), PCI_SECONDARY_BUS);
            sub_bus = pci_conf_read8(pseg->nr, bus, PCI_SLOT(devfn),
                                     PCI_FUNC(devfn), PCI_SUBORDINATE_BUS);

            spin_lock(&pseg->bus2bridge_lock);
            for ( ; sec_bus <= sub_bus; sec_bus++ )
            {
                pseg->bus2bridge[sec_bus].map = 1;
                pseg->bus2bridge[sec_bus].bus = bus;
                pseg->bus2bridge[sec_bus].devfn = devfn;
            }
            spin_unlock(&pseg->bus2bridge_lock);
            break;

        case DEV_TYPE_PCIe_ENDPOINT:
            pos = pci_find_cap_offset(pseg->nr, bus, PCI_SLOT(devfn),
                                      PCI_FUNC(devfn), PCI_CAP_ID_EXP);
            BUG_ON(!pos);
            cap = pci_conf_read16(pseg->nr, bus, PCI_SLOT(devfn),
                                  PCI_FUNC(devfn), pos + PCI_EXP_DEVCAP);
            if ( cap & PCI_EXP_DEVCAP_PHANTOM )
            {
                pdev->phantom_stride = 8 >> MASK_EXTR(cap,
                                                      PCI_EXP_DEVCAP_PHANTOM);
                if ( PCI_FUNC(devfn) >= pdev->phantom_stride )
                    pdev->phantom_stride = 0;
            }
            else
            {
Ejemplo n.º 5
0
Archivo: vga.c Proyecto: HackLinux/xen
void __init vga_endboot(void)
{
    if ( vga_puts == vga_noop_puts )
        return;

    printk("Xen is %s VGA console.\n",
           vgacon_keep ? "keeping" : "relinquishing");

    if ( !vgacon_keep )
        vga_puts = vga_noop_puts;
    else
    {
        int bus, devfn;

        for ( bus = 0; bus < 256; ++bus )
            for ( devfn = 0; devfn < 256; ++devfn )
            {
                const struct pci_dev *pdev;
                u8 b = bus, df = devfn, sb;

                spin_lock(&pcidevs_lock);
                pdev = pci_get_pdev(0, bus, devfn);
                spin_unlock(&pcidevs_lock);

                if ( !pdev ||
                     pci_conf_read16(0, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
                                     PCI_CLASS_DEVICE) != 0x0300 ||
                     !(pci_conf_read16(0, bus, PCI_SLOT(devfn),
                                       PCI_FUNC(devfn), PCI_COMMAND) &
                       (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) )
                    continue;

                while ( b )
                {
                    switch ( find_upstream_bridge(0, &b, &df, &sb) )
                    {
                    case 0:
                        b = 0;
                        break;
                    case 1:
                        switch ( pci_conf_read8(0, b, PCI_SLOT(df),
                                                PCI_FUNC(df),
                                                PCI_HEADER_TYPE) )
                        {
                        case PCI_HEADER_TYPE_BRIDGE:
                        case PCI_HEADER_TYPE_CARDBUS:
                            if ( pci_conf_read16(0, b, PCI_SLOT(df),
                                                 PCI_FUNC(df),
                                                 PCI_BRIDGE_CONTROL) &
                                 PCI_BRIDGE_CTL_VGA )
                                continue;
                            break;
                        }
                        break;
                    }
                    break;
                }
                if ( !b )
                {
                    printk(XENLOG_INFO "Boot video device %02x:%02x.%u\n",
                           bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
                    pci_hide_device(bus, devfn);
                }
            }
    }

    switch ( vga_console_info.video_type )
    {
    case XEN_VGATYPE_TEXT_MODE_3:
        if ( !vgacon_keep )
            memset(video, 0, columns * lines * 2);
        break;
    case XEN_VGATYPE_VESA_LFB:
    case XEN_VGATYPE_EFI_LFB:
        vesa_endboot(vgacon_keep);
        break;
    default:
        BUG();
    }
}
Ejemplo n.º 6
0
static void pcie_scanbus(struct pci_tegra_device *dev_parent)
{
	u8 subordinate_bus;
	u8 hdr_type;
	u8 next_bus_number;
	u32 device = 0;
	u32 id;
	struct pci_tegra_device *dev;
	u32 retry_count;

	next_bus_number = dev_parent->sec_bus;

next_device:
	retry_count = 6;
	if (device == 0x20) {
		/* Termination condition: Max number of devices reached.
		 * PCIe bus segment can only have 32 devices.
		 * */
		dev_parent->sub_bus = next_bus_number;
		if (!dev_parent->root_port) {
			/* Change the subordinate bus-number to the actual
			 * value of all buses on the hierarcy.
			*
			* Do this execpt for the root port.
			*/
			pci_conf_write8(dev_parent->bus, dev_parent->devfn,
				PCI_SUBORDINATE_BUS, next_bus_number);
		}
		return;
	}

	if (dev_parent->root_port && device != 0) {
		/* Sepcial Exit condition for root port.
		 * Root port only connect to one bridge or device.
		 */
		dev_parent->sub_bus = dev_parent->sec_bus;
		return;
	}

	while (--retry_count) {
		id = pci_conf_read32(dev_parent->sec_bus,
			PCI_DEVFN(device, 0), 0);
		if (id != 0xFFFFFFFF)
		{
		/* Found a valid device, break. Otherwise, retry a couple of
		 * times. It is possible that the bridges can take some time
		 * to settle and it will take couple of transcations to find
		 * the devcies behind the bridge.
		 * */
		/* FIXME: What should be the delay? */
			msleep(100);
			break;
		}
	}
	if (id == 0xFFFFFFFF) {
		/* Invalid device. Skip that one and look for next device */
		device++;
		goto next_device;
	}

	dev = alloc_pci_tegra_device();

	/* Fill the device information */
	dev->parent = dev_parent;
	dev->id = id;
	dev->bus = dev_parent->sec_bus;
	dev->devfn = PCI_DEVFN(device, 0);
	if (dev_parent->child == NULL) {
		dev_parent->child = dev;
		dev->prev = NULL;
	} else {
		/* Add dev to the list of devices on the same bus */
		struct pci_tegra_device *temp;

		temp = dev_parent->child;
		BUG_ON(temp != NULL);
		while (temp->next != NULL)
		temp = temp->next;
		temp->next = dev;
		dev->prev = temp;
	}

	hdr_type = pci_conf_read8(dev->bus, dev->devfn, PCI_HEADER_TYPE);
	if ((hdr_type & 0x7f) == 0x1) {
		/* Bridge device */

		/* Temporarily assign 0xff for the subordinate bus number as
		 * we don't * know how many devices are present behind this
		 * bridge.
		 * */
		subordinate_bus = 0xff;
		dev->sec_bus = next_bus_number + 1;

		pci_conf_write8(dev->bus, dev->devfn, PCI_PRIMARY_BUS,
			dev_parent->sec_bus);
		pci_conf_write8(dev->bus, dev->devfn, PCI_SECONDARY_BUS,
			dev->sec_bus);
		pci_conf_write8(dev->bus, dev->devfn, PCI_SUBORDINATE_BUS,
			subordinate_bus);

		/* Scan all the buses behind this bridge */
		pcie_scanbus(dev);

		next_bus_number = dev->sub_bus;
	} else if ((hdr_type & 0x7f) == 0x0) {

		/* PCI endpoint - Can be single function or multie function */
		pr_info("PCI endpoint (0x%x) is on bus = %d, device = %d\n",
			id, dev_parent->sec_bus, device);

	} else if ((hdr_type & 0x7f) == 0x2) {
		/* PC card device - Not handled */
		BUG();
	} else {
		BUG();
	}
	device++;
	goto next_device;
}