Introduce workaround for the (documented) bug with ATI/AMD SB600 and early SB700
periodic list cache. This workaround is based on similar patches in NetBSD and Linux and disables the (Advanced) Periodic List Cache on the affected devices using ATI/AMD specifc registers (as documented in the corresponding AMD register reference guide). Also remove a ton of stray whitespace introduced by the isochronous patches. Please take more care the next time. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41512 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
84464c202e
commit
3bb5704280
@ -141,6 +141,48 @@ EHCI::EHCI(pci_info *info, Stack *stack)
|
||||
TRACE("constructing new EHCI host controller driver\n");
|
||||
fInitOK = false;
|
||||
|
||||
// ATI/AMD SB600/SB700 periodic list cache workaround
|
||||
// Logic kindly borrowed from NetBSD PR 40056
|
||||
if (fPCIInfo->vendor_id == AMD_SBX00_VENDOR) {
|
||||
bool applyWorkaround = false;
|
||||
|
||||
if (fPCIInfo->device_id == AMD_SB600_EHCI_CONTROLLER) {
|
||||
// always apply on SB600
|
||||
applyWorkaround = true;
|
||||
} else if (fPCIInfo->device_id == AMD_SB700_SB800_EHCI_CONTROLLER) {
|
||||
// only apply on certain chipsets, determined by SMBus revision
|
||||
pci_info smbus;
|
||||
int32 index = 0;
|
||||
while (sPCIModule->get_nth_pci_info(index++, &smbus) >= B_OK) {
|
||||
if (smbus.vendor_id == AMD_SBX00_VENDOR
|
||||
&& smbus.device_id == AMD_SBX00_SMBUS_CONTROLLER) {
|
||||
|
||||
// Only applies to chipsets < SB710 (rev A14)
|
||||
if (smbus.revision == 0x3a || smbus.revision == 0x3b)
|
||||
applyWorkaround = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (applyWorkaround) {
|
||||
// According to AMD errata of SB700 and SB600 register documentation
|
||||
// this disables the Periodic List Cache on SB600 and the Advanced
|
||||
// Periodic List Cache on early SB700. Both the BSDs and Linux use
|
||||
// this workaround.
|
||||
|
||||
TRACE_ALWAYS("disabling SB600/SB700 periodic list cache\n");
|
||||
uint32 workaround = sPCIModule->read_pci_config(fPCIInfo->bus,
|
||||
fPCIInfo->device, fPCIInfo->function,
|
||||
AMD_SBX00_EHCI_MISC_REGISTER, 4);
|
||||
|
||||
sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device,
|
||||
fPCIInfo->function, AMD_SBX00_EHCI_MISC_REGISTER, 4,
|
||||
workaround | AMD_SBX00_EHCI_MISC_DISABLE_PERIODIC_LIST_CACHE);
|
||||
}
|
||||
}
|
||||
|
||||
// enable busmaster and memory mapped access
|
||||
uint16 command = sPCIModule->read_pci_config(fPCIInfo->bus,
|
||||
fPCIInfo->device, fPCIInfo->function, PCI_command, 2);
|
||||
@ -1657,7 +1699,6 @@ EHCI::FinishIsochronousTransfers()
|
||||
// Make sure to reset the frame bandwidth
|
||||
fFrameBandwidth[currentFrame] = MAX_AVAILABLE_BANDWIDTH;
|
||||
currentFrame = (currentFrame + 1) % EHCI_VFRAMELIST_ENTRIES_COUNT;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -335,4 +335,13 @@ typedef struct {
|
||||
// ToDo: Periodic Frame Span Traversal Node (FSTN, EHCI Spec 3.7)
|
||||
|
||||
|
||||
// Quirk registers and values
|
||||
#define AMD_SBX00_VENDOR 0x1002
|
||||
#define AMD_SBX00_SMBUS_CONTROLLER 0x4385
|
||||
#define AMD_SB600_EHCI_CONTROLLER 0x4386
|
||||
#define AMD_SB700_SB800_EHCI_CONTROLLER 0x4396
|
||||
|
||||
#define AMD_SBX00_EHCI_MISC_REGISTER 0x50 // Advanced config register
|
||||
#define AMD_SBX00_EHCI_MISC_DISABLE_PERIODIC_LIST_CACHE (1 << 27)
|
||||
|
||||
#endif // !EHCI_HARDWARE_H
|
||||
|
Loading…
Reference in New Issue
Block a user