XHCI USB: add MSI support
* similar to OHCI support by mmlr. * interrupt handler is removed on destruction.
This commit is contained in:
committed by
Jérôme Duval
parent
c45ac5ad59
commit
96adf3ffad
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <module.h>
|
||||
#include <PCI.h>
|
||||
#include <PCI_x86.h>
|
||||
#include <USB3.h>
|
||||
#include <KernelExport.h>
|
||||
|
||||
@@ -24,6 +25,7 @@
|
||||
#define USB_MODULE_NAME "xhci"
|
||||
|
||||
pci_module_info *XHCI::sPCIModule = NULL;
|
||||
pci_x86_module_info *XHCI::sPCIx86Module = NULL;
|
||||
|
||||
|
||||
static int32
|
||||
@@ -111,6 +113,8 @@ XHCI::XHCI(pci_info *info, Stack *stack)
|
||||
fRegisterArea(-1),
|
||||
fPCIInfo(info),
|
||||
fStack(stack),
|
||||
fIRQ(0),
|
||||
fUseMSI(false),
|
||||
fErstArea(-1),
|
||||
fDcbaArea(-1),
|
||||
fSpinlock(B_SPINLOCK_INITIALIZER),
|
||||
@@ -256,10 +260,24 @@ XHCI::XHCI(pci_info *info, Stack *stack)
|
||||
B_NORMAL_PRIORITY, (void *)this);
|
||||
resume_thread(fEventThread);
|
||||
|
||||
// Find the right interrupt vector, using MSIs if available.
|
||||
fIRQ = fPCIInfo->u.h0.interrupt_line;
|
||||
if (sPCIx86Module != NULL && sPCIx86Module->get_msi_count(fPCIInfo->bus,
|
||||
fPCIInfo->device, fPCIInfo->function) >= 1) {
|
||||
uint8 msiVector = 0;
|
||||
if (sPCIx86Module->configure_msi(fPCIInfo->bus, fPCIInfo->device,
|
||||
fPCIInfo->function, 1, &msiVector) == B_OK
|
||||
&& sPCIx86Module->enable_msi(fPCIInfo->bus, fPCIInfo->device,
|
||||
fPCIInfo->function) == B_OK) {
|
||||
TRACE_ALWAYS("using message signaled interrupts\n");
|
||||
fIRQ = msiVector;
|
||||
fUseMSI = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Install the interrupt handler
|
||||
TRACE("installing interrupt handler\n");
|
||||
install_io_interrupt_handler(fPCIInfo->u.h0.interrupt_line,
|
||||
InterruptHandler, (void *)this, 0);
|
||||
install_io_interrupt_handler(fIRQ, InterruptHandler, (void *)this, 0);
|
||||
|
||||
memset(fPortSpeeds, 0, sizeof(fPortSpeeds));
|
||||
memset(fPortSlots, 0, sizeof(fPortSlots));
|
||||
@@ -281,14 +299,28 @@ XHCI::~XHCI()
|
||||
delete_sem(fCmdCompSem);
|
||||
delete_sem(fFinishTransfersSem);
|
||||
delete_sem(fEventSem);
|
||||
wait_for_thread(fFinishThread, &result);
|
||||
wait_for_thread(fEventThread, &result);
|
||||
|
||||
remove_io_interrupt_handler(fIRQ, InterruptHandler, (void *)this);
|
||||
|
||||
delete_area(fRegisterArea);
|
||||
delete_area(fErstArea);
|
||||
for (uint32 i = 0; i < fScratchpadCount; i++)
|
||||
delete_area(fScratchpadArea[i]);
|
||||
delete_area(fDcbaArea);
|
||||
wait_for_thread(fFinishThread, &result);
|
||||
wait_for_thread(fEventThread, &result);
|
||||
|
||||
if (fUseMSI && sPCIx86Module != NULL) {
|
||||
sPCIx86Module->disable_msi(fPCIInfo->bus,
|
||||
fPCIInfo->device, fPCIInfo->function);
|
||||
sPCIx86Module->unconfigure_msi(fPCIInfo->bus,
|
||||
fPCIInfo->device, fPCIInfo->function);
|
||||
}
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
if (sPCIx86Module != NULL) {
|
||||
sPCIx86Module = NULL;
|
||||
put_module(B_PCI_X86_MODULE_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
struct pci_info;
|
||||
struct pci_module_info;
|
||||
struct pci_x86_module_info;
|
||||
struct xhci_td;
|
||||
struct xhci_device;
|
||||
struct xhci_endpoint;
|
||||
@@ -194,6 +195,7 @@ private:
|
||||
inline void WriteDoorReg32(uint32 reg, uint32 value);
|
||||
|
||||
static pci_module_info * sPCIModule;
|
||||
static pci_x86_module_info *sPCIx86Module;
|
||||
|
||||
uint8 * fCapabilityRegisters;
|
||||
uint32 fCapabilityLength;
|
||||
@@ -205,6 +207,8 @@ private:
|
||||
area_id fRegisterArea;
|
||||
pci_info * fPCIInfo;
|
||||
Stack * fStack;
|
||||
uint8 fIRQ;
|
||||
bool fUseMSI;
|
||||
|
||||
area_id fErstArea;
|
||||
xhci_erst_element * fErst;
|
||||
|
||||
Reference in New Issue
Block a user