📄 pcifixup.c
字号:
#include <stdio.h>
#include "typedef.h"
#include "low.h"
#include "list.h"
#include "pci.h"
void pci_fixup_i450nx(struct pci_dev far * d)
{
/*
* i450NX -- Find and scan all secondary buses on all PXB's.
*/
long pxb, reg;
u8 busno, suba, subb;
#ifdef DEBUG_VERSION
safe_printf("PCI: Searching for i450NX host bridges on %s\n", d->slot_name);
#endif
reg = 0xd0;
for(pxb=0; pxb<2; pxb++)
{
pci_read_config_byte(d, reg++, &busno);
pci_read_config_byte(d, reg++, &suba);
pci_read_config_byte(d, reg++, &subb);
#ifdef DEBUG_VERSION
safe_printf("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
#endif
if (busno)
pci_scan_bus(busno, pci_root_ops, NULL); /* Bus A */
if (suba < subb)
pci_scan_bus(suba+1, pci_root_ops, NULL); /* Bus B */
}
pcibios_last_bus = -1;
}
void pci_fixup_i450gx(struct pci_dev far *d)
{
/*
* i450GX and i450KX -- Find and scan all secondary buses.
* (called separately for each PCI bridge found)
*/
u8 busno;
pci_read_config_byte(d, 0x4a, &busno);
#ifdef DEBUG_VERSION
safe_printf("PCI: i440KX/GX host bridge %s: secondary bus %02x\n",
d->slot_name,busno);
#endif
pci_scan_bus(busno, pci_root_ops, NULL);
pcibios_last_bus = -1;
}
#if 0
/* Until we get proper handling pray the BIOS gets it right */
/*
* ServerWorks host bridges -- Find and scan all secondary buses.
* Register 0x44 contains first, 0x45 last bus number routed there.
*/
void pci_fixup_serverworks(struct pci_dev far * d)
{
u8 busno1, busno2;
pci_read_config_byte(d, 0x44, &busno1);
pci_read_config_byte(d, 0x45, &busno2);
if (busno2 < busno1)
busno2 = busno1;
if (busno2 > pcibios_last_bus)
{
pcibios_last_bus = busno2;
#ifdef DEBUG_VERSION
safe_printf("PCI: ServerWorks host bridge: last bus %02x\n", pcibios_last_bus);
#endif
}
}
#endif
#if 1
/* Our bus code shouldnt need this fixup any more. Delete once verified */
/*
* Compaq host bridges -- Find and scan all secondary buses.
* This time registers 0xc8 and 0xc9.
*/
void pci_fixup_compaq(struct pci_dev far *d)
{
u8 busno1, busno2;
pci_read_config_byte(d, 0xc8, &busno1);
pci_read_config_byte(d, 0xc9, &busno2);
if (busno2 < busno1)
busno2 = busno1;
if (busno2 > pcibios_last_bus)
{
pcibios_last_bus = busno2;
#ifdef DEBUG_VERSION
safe_printf("PCI: Compaq host bridge: last bus %02x\n", busno2);
#endif
}
}
#endif
void pci_fixup_umc_ide(struct pci_dev far * d)
{
/*
* UM8886BF IDE controller sets region type bits incorrectly,
* therefore they look like memory despite of them being I/O.
*/
int i;
safe_printf("PCI: Fixing base address flags for device %s\n", d->slot_name);
for(i=0; i<4; i++)
d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
}
void pci_fixup_ide_bases(struct pci_dev far * d)
{
int i;
/*
* PCI IDE controllers use non-standard I/O port decoding, respect it.
*/
if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
return;
#ifdef DEBUG_VERSION
safe_printf("PCI: IDE base address fixup for %s\n", d->slot_name);
#endif
for(i=0; i<4; i++)
{
struct resource *r = &d->resource[i];
if ((r->start & ~0x80) == 0x374)
{
r->start |= 2;
r->end = r->start;
}
}
}
void pci_fixup_ide_trash(struct pci_dev far *d)
{
int i;
/*
* There exist PCI IDE controllers which have utter garbage
* in first four base registers. Ignore that.
*/
#ifdef DEBUG_VERSION
safe_printf("PCI: IDE base address trash cleared for %s\n", d->slot_name);
#endif
for(i=0; i<4; i++)
{
d->resource[i].start = d->resource[i].end =
d->resource[i].flags = 0;
}
}
void pci_fixup_latency(struct pci_dev far * d)
{
/*
* SiS 5597 and 5598 chipsets require latency timer set to
* at most 32 to avoid lockups.
*/
#ifdef DEBUG_VERSION
safe_printf("PCI: Setting max latency to 32\n");
#endif
pcibios_max_latency = 32;
}
void pci_fixup_piix4_acpi(struct pci_dev far * d)
{
/*
* PIIX4 ACPI device: hardwired IRQ9
*/
d->irq = 9;
}
/*
* Nobody seems to know what this does. Damn.
*
* But it does seem to fix some unspecified problem
* with 'movntq' copies on Athlons.
*
* VIA 8363 chipset:
* - bit 7 at offset 0x55: Debug (RW)
*/
void pci_fixup_via_athlon_bug(struct pci_dev far * d)
{
u8 v;
pci_read_config_byte(d, 0x55, &v);
if (v & 0x80)
{
#ifdef DEBUG_VERSION
safe_printf("Trying to stomp on Athlon bug...\n");
#endif
v &= 0x7f; /* clear bit 55.7 */
pci_write_config_byte(d, 0x55, v);
}
}
extern struct pci_fixup pcibios_fixups[];
void quirk_passive_release(struct pci_dev far * dev)
{
struct pci_dev far * d = NULL;
unsigned char dlc;
/* We have to make sure a particular bit is set in the PIIX3
ISA bridge, so we have to go out and find it. */
while ((d = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, d)))
{
pci_read_config_byte(d, 0x82, &dlc);
if (!(dlc & 1<<1))
{
#ifdef DEBUG_VERSION
safe_printf("PCI: PIIX3: Enabling Passive Release on %s\n", d->slot_name);
#endif
dlc |= 1<<1;
pci_write_config_byte(d, 0x82, dlc);
}
}
}
/* The VIA VP2/VP3/MVP3 seem to have some 'features'. There may be a workaround
but VIA don't answer queries. If you happen to have good contacts at VIA
ask them for me please -- Alan
This appears to be BIOS not version dependent. So presumably there is a
chipset level fix */
extern long isa_dma_bridge_buggy; /* Exported */
extern long pci_pci_problems;
void quirk_isa_dma_hangs(struct pci_dev far * dev)
{
if (!isa_dma_bridge_buggy)
{
isa_dma_bridge_buggy=1;
#ifdef DEBUG_VERSION
safe_printf("Activating ISA DMA hang workarounds.\n");
#endif
}
}
/*
* Chipsets where PCI->PCI transfers vanish or hang
*/
void quirk_nopcipci(struct pci_dev far * dev)
{
if((pci_pci_problems & PCIPCI_FAIL) == 0)
{
#ifdef DEBUG_VERSION
safe_printf("Disabling direct PCI/PCI transfers.\n");
#endif
pci_pci_problems |= PCIPCI_FAIL;
}
}
/*
* Triton requires workarounds to be used by the drivers
*/
void quirk_triton(struct pci_dev far * dev)
{
if((pci_pci_problems & PCIPCI_TRITON) == 0)
{
#ifdef DEBUG_VERSION
safe_printf("Limiting direct PCI/PCI transfers.\n");
#endif
pci_pci_problems |= PCIPCI_TRITON;
}
}
/*
* VIA Apollo KT133 needs PCI latency patch
* Made according to a windows driver based patch by George E. Breese
* see PCI Latency Adjust on http://www.viahardware.com/download/viatweak.shtm
* Also see http://home.tiscalinet.de/au-ja/review-kt133a-1-en.html for
* the info on which Mr Breese based his work.
*
* Updated based on further information from the site and also on
* information provided by VIA
*/
void quirk_vialatency(struct pci_dev far * dev)
{
struct pci_dev far * p;
u8 rev;
u8 busarb;
/* Ok we have a potential problem chipset here. Now see if we have
a buggy southbridge */
p= pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, NULL);
if(p != NULL)
{
pci_read_config_byte(p, PCI_CLASS_REVISION, &rev);
/* 0x40 - 0x4f == 686B, 0x10 - 0x2f == 686A; thanks Dan Hollis */
/* Check for buggy part revisions */
if (rev < 0x40 || rev > 0x42)
return;
}
else
{
p = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, NULL);
if(p == NULL) /* No problem parts */
return;
pci_read_config_byte(p, PCI_CLASS_REVISION, &rev);
/* Check for buggy part revisions */
if (rev < 0x10 || rev > 0x12)
return;
}
/*
* Ok we have the problem. Now set the PCI master grant to
* occur every master grant. The apparent bug is that under high
* PCI load (quite common in Linux of course) you can get data
* loss when the CPU is held off the bus for 3 bus master requests
* This happens to include the IDE controllers....
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -