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");
|
TRACE("constructing new EHCI host controller driver\n");
|
||||||
fInitOK = false;
|
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
|
// enable busmaster and memory mapped access
|
||||||
uint16 command = sPCIModule->read_pci_config(fPCIInfo->bus,
|
uint16 command = sPCIModule->read_pci_config(fPCIInfo->bus,
|
||||||
fPCIInfo->device, fPCIInfo->function, PCI_command, 2);
|
fPCIInfo->device, fPCIInfo->function, PCI_command, 2);
|
||||||
@ -285,7 +327,7 @@ EHCI::EHCI(pci_info *info, Stack *stack)
|
|||||||
WriteOpReg(EHCI_USBINTR, fEnabledInterrupts);
|
WriteOpReg(EHCI_USBINTR, fEnabledInterrupts);
|
||||||
|
|
||||||
// structures don't span page boundaries
|
// structures don't span page boundaries
|
||||||
size_t itdListSize = EHCI_VFRAMELIST_ENTRIES_COUNT
|
size_t itdListSize = EHCI_VFRAMELIST_ENTRIES_COUNT
|
||||||
/ (B_PAGE_SIZE / sizeof(itd_entry)) * B_PAGE_SIZE;
|
/ (B_PAGE_SIZE / sizeof(itd_entry)) * B_PAGE_SIZE;
|
||||||
size_t sitdListSize = EHCI_VFRAMELIST_ENTRIES_COUNT
|
size_t sitdListSize = EHCI_VFRAMELIST_ENTRIES_COUNT
|
||||||
/ (B_PAGE_SIZE / sizeof(sitd_entry)) * B_PAGE_SIZE;
|
/ (B_PAGE_SIZE / sizeof(sitd_entry)) * B_PAGE_SIZE;
|
||||||
@ -351,13 +393,13 @@ EHCI::EHCI(pci_info *info, Stack *stack)
|
|||||||
sitd->back_phy = EHCI_ITEM_TERMINATE;
|
sitd->back_phy = EHCI_ITEM_TERMINATE;
|
||||||
fSitdEntries[i] = sitd;
|
fSitdEntries[i] = sitd;
|
||||||
TRACE("sitd entry %ld %p 0x%lx\n", i, sitd, sitd->this_phy);
|
TRACE("sitd entry %ld %p 0x%lx\n", i, sitd, sitd->this_phy);
|
||||||
|
|
||||||
ehci_itd *itd = &itds[i].itd;
|
ehci_itd *itd = &itds[i].itd;
|
||||||
itd->this_phy = itdPhysicalBase | EHCI_ITEM_TYPE_ITD;
|
itd->this_phy = itdPhysicalBase | EHCI_ITEM_TYPE_ITD;
|
||||||
itd->next_phy = sitd->this_phy;
|
itd->next_phy = sitd->this_phy;
|
||||||
fItdEntries[i] = itd;
|
fItdEntries[i] = itd;
|
||||||
TRACE("itd entry %ld %p 0x%lx\n", i, itd, itd->this_phy);
|
TRACE("itd entry %ld %p 0x%lx\n", i, itd, itd->this_phy);
|
||||||
|
|
||||||
sitdPhysicalBase += sizeof(sitd_entry);
|
sitdPhysicalBase += sizeof(sitd_entry);
|
||||||
itdPhysicalBase += sizeof(itd_entry);
|
itdPhysicalBase += sizeof(itd_entry);
|
||||||
if ((sitdPhysicalBase & 0x10) != 0 || (itdPhysicalBase & 0x10) != 0)
|
if ((sitdPhysicalBase & 0x10) != 0 || (itdPhysicalBase & 0x10) != 0)
|
||||||
@ -399,7 +441,7 @@ EHCI::EHCI(pci_info *info, Stack *stack)
|
|||||||
fItdEntries[i & (EHCI_VFRAMELIST_ENTRIES_COUNT - 1)]->this_phy;
|
fItdEntries[i & (EHCI_VFRAMELIST_ENTRIES_COUNT - 1)]->this_phy;
|
||||||
TRACE("periodic entry %ld linked to 0x%lx\n", i, fPeriodicFrameList[i]);
|
TRACE("periodic entry %ld linked to 0x%lx\n", i, fPeriodicFrameList[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the array that will keep bandwidth information
|
// Create the array that will keep bandwidth information
|
||||||
fFrameBandwidth = new(std::nothrow) uint16[EHCI_VFRAMELIST_ENTRIES_COUNT];
|
fFrameBandwidth = new(std::nothrow) uint16[EHCI_VFRAMELIST_ENTRIES_COUNT];
|
||||||
for (int32 i = 0; i < EHCI_VFRAMELIST_ENTRIES_COUNT; i++) {
|
for (int32 i = 0; i < EHCI_VFRAMELIST_ENTRIES_COUNT; i++) {
|
||||||
@ -642,7 +684,7 @@ EHCI::SubmitIsochronous(Transfer *transfer)
|
|||||||
// Find the entry where to start inserting the first Isochronous descriptor
|
// Find the entry where to start inserting the first Isochronous descriptor
|
||||||
if (isochronousData->flags & USB_ISO_ASAP ||
|
if (isochronousData->flags & USB_ISO_ASAP ||
|
||||||
isochronousData->starting_frame_number == NULL) {
|
isochronousData->starting_frame_number == NULL) {
|
||||||
|
|
||||||
uint32 threshold = (ReadCapReg32(EHCI_HCCPARAMS)
|
uint32 threshold = (ReadCapReg32(EHCI_HCCPARAMS)
|
||||||
>> EHCI_HCCPARAMS_IPT_SHIFT) & EHCI_HCCPARAMS_IPT_MASK;
|
>> EHCI_HCCPARAMS_IPT_SHIFT) & EHCI_HCCPARAMS_IPT_MASK;
|
||||||
TRACE("threshold: %ld\n", threshold);
|
TRACE("threshold: %ld\n", threshold);
|
||||||
@ -677,7 +719,7 @@ EHCI::SubmitIsochronous(Transfer *transfer)
|
|||||||
TRACE_ERROR("unable to allocate itd buffer\n");
|
TRACE_ERROR("unable to allocate itd buffer\n");
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(bufferLog, 0, dataLength);
|
memset(bufferLog, 0, dataLength);
|
||||||
|
|
||||||
addr_t currentPhy = bufferPhy;
|
addr_t currentPhy = bufferPhy;
|
||||||
@ -713,16 +755,16 @@ EHCI::SubmitIsochronous(Transfer *transfer)
|
|||||||
itd->buffer_phy[1] |= (pipe->MaxPacketSize() & EHCI_ITD_MAXPACKETSIZE_MASK)
|
itd->buffer_phy[1] |= (pipe->MaxPacketSize() & EHCI_ITD_MAXPACKETSIZE_MASK)
|
||||||
| (directionIn << EHCI_ITD_DIR_SHIFT);
|
| (directionIn << EHCI_ITD_DIR_SHIFT);
|
||||||
itd->buffer_phy[2] |= (1 << EHCI_ITD_MUL_SHIFT);
|
itd->buffer_phy[2] |= (1 << EHCI_ITD_MUL_SHIFT);
|
||||||
|
|
||||||
TRACE("isochronous filled itd buffer_phy[0,1,2] 0x%lx, 0x%lx 0x%lx\n",
|
TRACE("isochronous filled itd buffer_phy[0,1,2] 0x%lx, 0x%lx 0x%lx\n",
|
||||||
itd->buffer_phy[0], itd->buffer_phy[1], itd->buffer_phy[2]);
|
itd->buffer_phy[0], itd->buffer_phy[1], itd->buffer_phy[2]);
|
||||||
|
|
||||||
LinkITDescriptors(itd, &fItdEntries[currentFrame]);
|
LinkITDescriptors(itd, &fItdEntries[currentFrame]);
|
||||||
fFrameBandwidth[currentFrame] -= bandwidth;
|
fFrameBandwidth[currentFrame] -= bandwidth;
|
||||||
currentFrame = (currentFrame + 1) & (EHCI_VFRAMELIST_ENTRIES_COUNT - 1);
|
currentFrame = (currentFrame + 1) & (EHCI_VFRAMELIST_ENTRIES_COUNT - 1);
|
||||||
frameCount++;
|
frameCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("isochronous filled itds count %d\n", itdIndex);
|
TRACE("isochronous filled itds count %d\n", itdIndex);
|
||||||
|
|
||||||
// Add transfer to the list
|
// Add transfer to the list
|
||||||
@ -1190,7 +1232,7 @@ EHCI::AddPendingIsochronousTransfer(Transfer *transfer, ehci_itd **isoRequest,
|
|||||||
data->buffer_phy = bufferPhy;
|
data->buffer_phy = bufferPhy;
|
||||||
data->buffer_log = bufferLog;
|
data->buffer_log = bufferLog;
|
||||||
data->buffer_size = bufferSize;
|
data->buffer_size = bufferSize;
|
||||||
|
|
||||||
// Put in the isochronous transfer list
|
// Put in the isochronous transfer list
|
||||||
if (!LockIsochronous()) {
|
if (!LockIsochronous()) {
|
||||||
delete data;
|
delete data;
|
||||||
@ -1561,7 +1603,7 @@ EHCI::FinishIsochronousTransfers()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
bool transferDone = false;
|
bool transferDone = false;
|
||||||
|
|
||||||
uint32 frame = (ReadOpReg(EHCI_FRINDEX) / 8 )
|
uint32 frame = (ReadOpReg(EHCI_FRINDEX) / 8 )
|
||||||
& (EHCI_FRAMELIST_ENTRIES_COUNT - 1);
|
& (EHCI_FRAMELIST_ENTRIES_COUNT - 1);
|
||||||
uint32 currentFrame = (frame + EHCI_VFRAMELIST_ENTRIES_COUNT - 5)
|
uint32 currentFrame = (frame + EHCI_VFRAMELIST_ENTRIES_COUNT - 5)
|
||||||
@ -1578,7 +1620,7 @@ EHCI::FinishIsochronousTransfers()
|
|||||||
}
|
}
|
||||||
|
|
||||||
ehci_itd *itd = fItdEntries[currentFrame];
|
ehci_itd *itd = fItdEntries[currentFrame];
|
||||||
|
|
||||||
TRACE("FinishIsochronousTransfers itd %p phy 0x%lx prev (%p/0x%lx)"
|
TRACE("FinishIsochronousTransfers itd %p phy 0x%lx prev (%p/0x%lx)"
|
||||||
" at frame %ld\n", itd, itd->this_phy, itd->prev,
|
" at frame %ld\n", itd, itd->this_phy, itd->prev,
|
||||||
itd->prev != NULL ? itd->prev->this_phy : 0, currentFrame);
|
itd->prev != NULL ? itd->prev->this_phy : 0, currentFrame);
|
||||||
@ -1596,7 +1638,7 @@ EHCI::FinishIsochronousTransfers()
|
|||||||
TRACE("FinishIsochronousTransfers unprocessed active itd\n");
|
TRACE("FinishIsochronousTransfers unprocessed active itd\n");
|
||||||
}
|
}
|
||||||
UnlinkITDescriptors(itd, &fItdEntries[currentFrame]);
|
UnlinkITDescriptors(itd, &fItdEntries[currentFrame]);
|
||||||
|
|
||||||
// Process the transfer if we found the last descriptor
|
// Process the transfer if we found the last descriptor
|
||||||
isochronous_transfer_data *transfer
|
isochronous_transfer_data *transfer
|
||||||
= FindIsochronousTransfer(itd);
|
= FindIsochronousTransfer(itd);
|
||||||
@ -1639,7 +1681,7 @@ EHCI::FinishIsochronousTransfers()
|
|||||||
FreeDescriptor(transfer->descriptors[i]);
|
FreeDescriptor(transfer->descriptors[i]);
|
||||||
|
|
||||||
TRACE("FinishIsochronousTransfers descriptors freed\n");
|
TRACE("FinishIsochronousTransfers descriptors freed\n");
|
||||||
|
|
||||||
delete [] transfer->descriptors;
|
delete [] transfer->descriptors;
|
||||||
delete transfer->transfer;
|
delete transfer->transfer;
|
||||||
fStack->FreeChunk(transfer->buffer_log,
|
fStack->FreeChunk(transfer->buffer_log,
|
||||||
@ -1651,13 +1693,12 @@ EHCI::FinishIsochronousTransfers()
|
|||||||
}
|
}
|
||||||
itd = itd->prev;
|
itd = itd->prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("FinishIsochronousTransfers next frame\n");
|
TRACE("FinishIsochronousTransfers next frame\n");
|
||||||
|
|
||||||
// Make sure to reset the frame bandwidth
|
// Make sure to reset the frame bandwidth
|
||||||
fFrameBandwidth[currentFrame] = MAX_AVAILABLE_BANDWIDTH;
|
fFrameBandwidth[currentFrame] = MAX_AVAILABLE_BANDWIDTH;
|
||||||
currentFrame = (currentFrame + 1) % EHCI_VFRAMELIST_ENTRIES_COUNT;
|
currentFrame = (currentFrame + 1) % EHCI_VFRAMELIST_ENTRIES_COUNT;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2070,7 +2111,7 @@ EHCI::CreateItdDescriptor()
|
|||||||
TRACE_ERROR("failed to allocate a itd\n");
|
TRACE_ERROR("failed to allocate a itd\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(result, 0, sizeof(ehci_itd));
|
memset(result, 0, sizeof(ehci_itd));
|
||||||
result->this_phy = (addr_t)physicalAddress;
|
result->this_phy = (addr_t)physicalAddress;
|
||||||
result->next_phy = EHCI_ITEM_TERMINATE;
|
result->next_phy = EHCI_ITEM_TERMINATE;
|
||||||
@ -2093,7 +2134,7 @@ EHCI::CreateSitdDescriptor()
|
|||||||
memset(result, 0, sizeof(ehci_sitd));
|
memset(result, 0, sizeof(ehci_sitd));
|
||||||
result->this_phy = (addr_t)physicalAddress | EHCI_ITEM_TYPE_SITD;
|
result->this_phy = (addr_t)physicalAddress | EHCI_ITEM_TYPE_SITD;
|
||||||
result->next_phy = EHCI_ITEM_TERMINATE;
|
result->next_phy = EHCI_ITEM_TERMINATE;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2178,7 +2219,7 @@ EHCI::UnlinkSITDescriptors(ehci_sitd *sitd, ehci_sitd **last)
|
|||||||
sitd->prev->next = sitd->next;
|
sitd->prev->next = sitd->next;
|
||||||
if (sitd->next != NULL)
|
if (sitd->next != NULL)
|
||||||
sitd->next->prev = sitd->prev;
|
sitd->next->prev = sitd->prev;
|
||||||
if (sitd == *last)
|
if (sitd == *last)
|
||||||
*last = sitd->prev;
|
*last = sitd->prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2333,7 +2374,7 @@ EHCI::ReadIsochronousDescriptorChain(isochronous_transfer_data *transfer)
|
|||||||
{
|
{
|
||||||
iovec *vector = transfer->transfer->Vector();
|
iovec *vector = transfer->transfer->Vector();
|
||||||
size_t vectorCount = transfer->transfer->VectorCount();
|
size_t vectorCount = transfer->transfer->VectorCount();
|
||||||
|
|
||||||
size_t vectorOffset = 0;
|
size_t vectorOffset = 0;
|
||||||
size_t vectorIndex = 0;
|
size_t vectorIndex = 0;
|
||||||
usb_isochronous_data *isochronousData
|
usb_isochronous_data *isochronousData
|
||||||
@ -2341,7 +2382,7 @@ EHCI::ReadIsochronousDescriptorChain(isochronous_transfer_data *transfer)
|
|||||||
uint32 packet = 0;
|
uint32 packet = 0;
|
||||||
size_t totalLength = 0;
|
size_t totalLength = 0;
|
||||||
size_t bufferOffset = 0;
|
size_t bufferOffset = 0;
|
||||||
|
|
||||||
size_t packetSize = transfer->transfer->DataLength();
|
size_t packetSize = transfer->transfer->DataLength();
|
||||||
packetSize /= isochronousData->packet_count;
|
packetSize /= isochronousData->packet_count;
|
||||||
|
|
||||||
@ -2349,19 +2390,19 @@ EHCI::ReadIsochronousDescriptorChain(isochronous_transfer_data *transfer)
|
|||||||
ehci_itd *itd = transfer->descriptors[i];
|
ehci_itd *itd = transfer->descriptors[i];
|
||||||
for (uint32 j = 0; j <= itd->last_token
|
for (uint32 j = 0; j <= itd->last_token
|
||||||
&& packet < isochronousData->packet_count; j++) {
|
&& packet < isochronousData->packet_count; j++) {
|
||||||
|
|
||||||
size_t bufferSize = (itd->token[j] >> EHCI_ITD_TLENGTH_SHIFT)
|
size_t bufferSize = (itd->token[j] >> EHCI_ITD_TLENGTH_SHIFT)
|
||||||
& EHCI_ITD_TLENGTH_MASK;
|
& EHCI_ITD_TLENGTH_MASK;
|
||||||
isochronousData->packet_descriptors[packet].actual_length =
|
isochronousData->packet_descriptors[packet].actual_length =
|
||||||
bufferSize;
|
bufferSize;
|
||||||
|
|
||||||
if (bufferSize > 0)
|
if (bufferSize > 0)
|
||||||
isochronousData->packet_descriptors[packet].status = B_OK;
|
isochronousData->packet_descriptors[packet].status = B_OK;
|
||||||
else
|
else
|
||||||
isochronousData->packet_descriptors[packet].status = B_ERROR;
|
isochronousData->packet_descriptors[packet].status = B_ERROR;
|
||||||
|
|
||||||
totalLength += bufferSize;
|
totalLength += bufferSize;
|
||||||
|
|
||||||
size_t offset = bufferOffset;
|
size_t offset = bufferOffset;
|
||||||
while (bufferSize > 0) {
|
while (bufferSize > 0) {
|
||||||
size_t length = min_c(bufferSize,
|
size_t length = min_c(bufferSize,
|
||||||
@ -2371,7 +2412,7 @@ EHCI::ReadIsochronousDescriptorChain(isochronous_transfer_data *transfer)
|
|||||||
offset += length;
|
offset += length;
|
||||||
vectorOffset += length;
|
vectorOffset += length;
|
||||||
bufferSize -= length;
|
bufferSize -= length;
|
||||||
|
|
||||||
if (vectorOffset >= vector[vectorIndex].iov_len) {
|
if (vectorOffset >= vector[vectorIndex].iov_len) {
|
||||||
if (++vectorIndex >= vectorCount) {
|
if (++vectorIndex >= vectorCount) {
|
||||||
TRACE("read isodescriptor chain (%ld bytes, no more "
|
TRACE("read isodescriptor chain (%ld bytes, no more "
|
||||||
@ -2382,17 +2423,17 @@ EHCI::ReadIsochronousDescriptorChain(isochronous_transfer_data *transfer)
|
|||||||
vectorOffset = 0;
|
vectorOffset = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferOffset += packetSize;
|
bufferOffset += packetSize;
|
||||||
if (bufferOffset >= transfer->buffer_size)
|
if (bufferOffset >= transfer->buffer_size)
|
||||||
return totalLength;
|
return totalLength;
|
||||||
|
|
||||||
packet++;
|
packet++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("ReadIsochronousDescriptorChain packet count %ld\n", packet);
|
TRACE("ReadIsochronousDescriptorChain packet count %ld\n", packet);
|
||||||
|
|
||||||
return totalLength;
|
return totalLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,4 +335,13 @@ typedef struct {
|
|||||||
// ToDo: Periodic Frame Span Traversal Node (FSTN, EHCI Spec 3.7)
|
// 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
|
#endif // !EHCI_HARDWARE_H
|
||||||
|
Loading…
Reference in New Issue
Block a user