📄 pcifixup.c
字号:
*
* VIA only apply this fix when an SB Live! is present but under
* both Linux and Windows this isnt enough, and we have seen
* corruption without SB Live! but with things like 3 UDMA IDE
* controllers. So we ignore that bit of the VIA recommendation..
*/
pci_read_config_byte(dev, 0x76, &busarb);
/* Set bit 4 and bi 5 of byte 76 to 0x01
"Master priority rotation on every PCI master grant */
busarb &= ~(1<<5);
busarb |= (1<<4);
pci_write_config_byte(dev, 0x76, busarb);
#ifdef DEBUG_VERSION
safe_printf("Applying VIA southbridge workaround.\n");
#endif
}
/*
* VIA Apollo VP3 needs ETBF on BT848/878
*/
void quirk_viaetbf(struct pci_dev far * dev)
{
if((pci_pci_problems & PCIPCI_VIAETBF) == 0)
{
#ifdef DEBUG_VERSION
safe_printf("Limiting direct PCI/PCI transfers.\n");
#endif
pci_pci_problems |= PCIPCI_VIAETBF;
}
}
void quirk_vsfx(struct pci_dev far * dev)
{
if( (pci_pci_problems & PCIPCI_VSFX) == 0)
{
#ifdef DEBUG_VERSION
safe_printf("Limiting direct PCI/PCI transfers.\n");
#endif
pci_pci_problems |= PCIPCI_VSFX;
}
}
/*
* Natoma has some interesting boundary conditions with Zoran stuff
* at least
*/
void quirk_natoma(struct pci_dev far * dev)
{
if( (pci_pci_problems & PCIPCI_NATOMA) == 0)
{
#ifdef DEBUG_VERSION
safe_printf("Limiting direct PCI/PCI transfers.\n");
#endif
pci_pci_problems |= PCIPCI_NATOMA;
}
}
/*
* S3 868 and 968 chips report region size equal to 32M, but they decode 64M.
* If it's needed, re-allocate the region.
*/
void quirk_s3_64M(struct pci_dev far * dev)
{
struct resource far * r = &dev->resource[0];
if ((r->start & 0x3ffffff) || r->end != r->start + 0x3ffffff)
{
r->start = 0;
r->end = 0x3ffffff;
}
}
void quirk_io_region(struct pci_dev far * dev, unsigned long region, unsigned long size,
long nr)
{
region &= ~(size - 1);
if (region)
{
struct resource far * res = dev->resource + nr;
res->name = dev->name;
res->start = region;
res->end = region + size - 1;
res->flags = IORESOURCE_IO;
pci_claim_resource(dev, nr);
}
}
/*
* Let's make the southbridge information explicit instead
* of having to worry about people probing the ACPI areas,
* for example.. (Yes, it happens, and if you read the wrong
* ACPI register it will put the machine to sleep with no
* way of waking it up again. Bummer).
*
* ALI M7101: Two IO regions pointed to by words at
* 0xE0 (64 bytes of ACPI registers)
* 0xE2 (32 bytes of SMB registers)
*/
void quirk_ali7101_acpi(struct pci_dev far * dev)
{
u16 region;
pci_read_config_word(dev, 0xE0, ®ion);
quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES);
pci_read_config_word(dev, 0xE2, ®ion);
quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1);
}
/*
* PIIX4 ACPI: Two IO regions pointed to by longwords at
* 0x40 (64 bytes of ACPI registers)
* 0x90 (32 bytes of SMB registers)
*/
void quirk_piix4_acpi(struct pci_dev far * dev)
{
u32 region;
pci_read_config_dword(dev, 0x40, ®ion);
quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES);
pci_read_config_dword(dev, 0x90, ®ion);
quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1);
}
/*
* VIA ACPI: One IO region pointed to by longword at
* 0x48 or 0x20 (256 bytes of ACPI registers)
*/
void quirk_vt82c586_acpi(struct pci_dev far * dev)
{
u8 rev;
u32 region;
pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
if (rev & 0x10)
{
pci_read_config_dword(dev, 0x48, ®ion);
region &= PCI_BASE_ADDRESS_IO_MASK;
quirk_io_region(dev, region, 256, PCI_BRIDGE_RESOURCES);
}
}
/*
* VIA VT82C686 ACPI: Three IO region pointed to by (long)words at
* 0x48 (256 bytes of ACPI registers)
* 0x70 (128 bytes of hardware monitoring register)
* 0x90 (16 bytes of SMB registers)
*/
void quirk_vt82c686_acpi(struct pci_dev far * dev)
{
u16 hm;
u32 smb;
quirk_vt82c586_acpi(dev);
pci_read_config_word(dev, 0x70, &hm);
hm &= PCI_BASE_ADDRESS_IO_MASK;
quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1);
pci_read_config_dword(dev, 0x90, &smb);
smb &= PCI_BASE_ADDRESS_IO_MASK;
quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2);
}
#ifdef CONFIG_X86_IO_APIC
long nr_ioapics;
/*
* VIA 686A/B: If an IO-APIC is active, we need to route all on-chip
* devices to the external APIC.
*
* TODO: When we have device-specific interrupt routers,
* this code will go away from quirks.
*/
void quirk_via_ioapic(struct pci_dev far * dev)
{
u8 tmp;
if (nr_ioapics < 1)
tmp = 0; /* nothing routed to external APIC */
else
tmp = 0x1f; /* all known bits (4-0) routed to external APIC */
#ifdef DEBUG_VERSION
safe_printf("PCI: %sbling Via external APIC routing\n",tmp == 0 ? "Disa" : "Ena");
#endif
/* Offset 0x58: External APIC IRQ output control */
pci_write_config_byte (dev, 0x58, tmp);
}
#endif /* CONFIG_X86_IO_APIC */
/*
* Via 686A/B: The PCI_INTERRUPT_LINE register for the on-chip
* devices, USB0/1, AC97, MC97, and ACPI, has an unusual feature:
* when written, it makes an internal connection to the PIC.
* For these devices, this register is defined to be 4 bits wide.
* Normally this is fine. However for IO-APIC motherboards, or
* non-x86 architectures (yes Via exists on PPC among other places),
* we must mask the PCI_INTERRUPT_LINE value versus 0xf to get
* interrupts delivered properly.
*
* TODO: When we have device-specific interrupt routers,
* quirk_via_irqpic will go away from quirks.
*/
/*
* FIXME: it is questionable that quirk_via_acpi
* is needed. It shows up as an ISA bridge, and does not
* support the PCI_INTERRUPT_LINE register at all. Therefore
* it seems like setting the pci_dev's 'irq' to the
* value of the ACPI SCI interrupt is only done for convenience.
* -jgarzik
*/
void quirk_via_acpi(struct pci_dev far * d)
{
/*
* VIA ACPI device: SCI IRQ line in PCI config byte 0x42
*/
u8 irq;
pci_read_config_byte(d, 0x42, &irq);
irq &= 0xf;
if (irq && (irq != 2))
d->irq = irq;
}
void quirk_via_irqpic(struct pci_dev far * dev)
{
u8 irq, new_irq = dev->irq & 0xf;
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
if (new_irq != irq)
{
#ifdef DEBUG_VERSION
safe_printf("PCI: Via IRQ fixup for %s, from %d to %d\n",
dev->slot_name, irq, new_irq);
#endif
udelay(50);
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
}
}
/*
* PIIX3 USB: We have to disable USB interrupts that are
* hardwired to PIRQD# and may be shared with an
* external device.
*
* Legacy Support Register (LEGSUP):
* bit13: USB PIRQ Enable (USBPIRQDEN),
* bit4: Trap/SMI On IRQ Enable (USBSMIEN).
*
* We mask out all r/wc bits, too.
*/
void quirk_piix3_usb(struct pci_dev far * dev)
{
u16 legsup;
pci_read_config_word(dev, 0xc0, &legsup);
legsup &= 0x50ef;
pci_write_config_word(dev, 0xc0, legsup);
}
/*
* VIA VT82C598 has its device ID settable and many BIOSes
* set it to the ID of VT82C597 for backward compatibility.
* We need to switch it off to be able to recognize the real
* type of the chip.
*/
void quirk_vt82c598_id(struct pci_dev far * dev)
{
pci_write_config_byte(dev, 0xfc, 0);
pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);
}
/*
* CardBus controllers have a legacy base address that enables them
* to respond as i82365 pcmcia controllers. We don't want them to
* do this even if the Linux CardBus driver is not loaded, because
* the Linux i82365 driver does not (and should not) handle CardBus.
*/
void quirk_cardbus_legacy(struct pci_dev far * dev)
{
if ((PCI_CLASS_BRIDGE_CARDBUS << 8) ^ dev->class)
return;
pci_write_config_dword(dev, PCI_CB_LEGACY_MODE_BASE, 0);
}
extern struct pci_fixup pci_fixups[];
void pci_do_fixups(struct pci_dev far * dev, int pass, struct pci_fixup far * f)
{
while (f->pass)
{
if (f->pass == pass &&
(f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
(f->device == dev->device || f->device == (u16) PCI_ANY_ID))
{
#ifdef DEBUG_VERSION
safe_printf("PCI: Calling quirk %p for %s\n", f->hook, dev->slot_name);
#endif
f->hook(dev);
}
f++;
}
}
void pci_fixup_device(int pass, struct pci_dev far * dev)
{
pci_do_fixups(dev, pass, pcibios_fixups);
pci_do_fixups(dev, pass, pci_fixups);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -